Merge branch 'wip' of gitlab.psi.ch-samenv:samenv/frappy into wip

This commit is contained in:
zolliker 2023-09-22 13:29:23 +02:00
commit 3b997d7d86
29 changed files with 1010 additions and 813 deletions

View File

@ -11,6 +11,7 @@ Mod('sea_addons',
Mod('t_be_filter', Mod('t_be_filter',
'frappy_psi.sea.SeaReadable', 'frappy_psi.sea.SeaReadable',
'Be filter T',
io='sea_addons', io='sea_addons',
sea_object='t_be_filter', sea_object='t_be_filter',
) )

View File

@ -0,0 +1,51 @@
Node('flamesample.psi.ch',
'flame sample thermometers and heater',
interface = 'tcp://5000',
)
Mod('lscio',
'frappy_psi.ls372.StringIO',
'sample channels LS372 io',
uri = 'flamedil-ls.psi.ch:7777',
)
Mod('lsc_channel',
'frappy_psi.ls372.Switcher',
'channel switcher sample ls372',
io='lscio',
value = 3,
)
Mod('ts_low',
'frappy_psi.ls372.TemperatureLoop',
'sample RuOX',
channel = 3,
switcher = 'lsc_channel',
minrange=13,
range=22,
tolerance = 0.1,
htrrng=4,
)
Mod('ts_high',
'frappy_psi.ls372.TemperatureLoop',
'sample Cernox',
channel = 1,
switcher = 'lsc_channel',
minrange=9,
range=22,
tolerance = 0.1,
htrrng=5,
minheater=5e-4,
)
Mod('ts',
'frappy_psi.parmod.SwitchDriv',
'automatically switching between ts_low and ts_high',
value=Param(unit='K'),
low='ts_low',
high='ts_high',
min_high=0.6,
max_low=1.7,
tolerance=0.1,
)

View File

@ -1,24 +0,0 @@
Node('ft.config.sea.psi.ch',
'FW ILL furnace with W5 thermnocouple (1800 K), old power rack',
)
Mod('sea_main',
'frappy_psi.sea.SeaClient',
'main sea connection for fw.config',
config='ft.config',
service='main',
)
Mod('ts',
'frappy_psi.sea.SeaDrivable', '',
io='sea_main',
sea_object='tt',
rel_paths=['.', 'ts'],
)
Mod('t2',
'frappy_psi.sea.SeaReadable', '',
io='sea_main',
sea_object='tt',
rel_paths=['t2'],
)

View File

@ -4,7 +4,7 @@ Node('eurotherm.config.sea.psi.ch',
Mod('sea_main', Mod('sea_main',
'frappy_psi.sea.SeaClient', 'frappy_psi.sea.SeaClient',
'main sea connection for haakeuro.config', 'main sea connection for haakeuro.config',
config = 'haakeuro.config', config = 'eurotherm.config',
service = 'main', service = 'main',
meaning=('temperature', 11), meaning=('temperature', 11),
) )

View File

@ -36,7 +36,7 @@ Mod('vacuumpump',
) )
Mod('table', Mod('table',
'frappy_psi.sea.SeaModule', 'frappy_psi.sea.SeaModule', '',
io='sea_main', io='sea_main',
sea_object='table', sea_object='table',
) )

View File

@ -1,3 +1,8 @@
Node('flamemag.psi.ch',
'flame magnet',
interface='tcp://5000'
)
Mod('cio', Mod('cio',
'frappy_psi.cryoltd.IO', 'frappy_psi.cryoltd.IO',
'IO to cryo ltd software', 'IO to cryo ltd software',
@ -14,6 +19,7 @@ Mod('B',
'frappy_psi.cryoltd.MainField', 'frappy_psi.cryoltd.MainField',
'magnetic field', 'magnetic field',
channel='Main', channel='Main',
main='main',
constraint=80000.0, constraint=80000.0,
target=Param( target=Param(
max=35000.0, max=35000.0,
@ -27,6 +33,8 @@ Mod('B',
overshoot={'o': 1.0, 't': 180.0}, overshoot={'o': 1.0, 't': 180.0},
degauss={'s': 500.0, 'd': 30.0, 'f': 5.0, 't': 120.0}, degauss={'s': 500.0, 'd': 30.0, 'f': 5.0, 't': 120.0},
tolerance=5.0, tolerance=5.0,
wait_switch_on = 30,
wait_switch_off = 30,
wait_stable_field=180.0, wait_stable_field=180.0,
) )
@ -34,6 +42,7 @@ Mod('Bx',
'frappy_psi.cryoltd.ComponentField', 'frappy_psi.cryoltd.ComponentField',
'magnetic field x component', 'magnetic field x component',
channel='VMX', channel='VMX',
main='main',
check_against='B', check_against='B',
target=Param( target=Param(
max=200.0, max=200.0,
@ -50,6 +59,7 @@ Mod('By',
'frappy_psi.cryoltd.ComponentField', 'frappy_psi.cryoltd.ComponentField',
'magnetic field y component', 'magnetic field y component',
channel='VMY', channel='VMY',
main='main',
check_against='B', check_against='B',
target=Param( target=Param(
max=100.0, max=100.0,
@ -66,6 +76,7 @@ Mod('Bz',
'frappy_psi.cryoltd.ComponentField', 'frappy_psi.cryoltd.ComponentField',
'magnetic field z component', 'magnetic field z component',
channel='VMZ', channel='VMZ',
main='main',
check_against='B', check_against='B',
target=Param( target=Param(
max=100.0, max=100.0,
@ -82,130 +93,132 @@ Mod('compressorA',
'frappy_psi.cryoltd.Compressor', 'frappy_psi.cryoltd.Compressor',
'compressor A', 'compressor A',
channel='A', channel='A',
main='main',
) )
Mod('compressorB', Mod('compressorB',
'frappy_psi.cryoltd.Compressor', 'frappy_psi.cryoltd.Compressor',
'compressor B', 'compressor B',
channel='B', channel='B',
main='main',
) )
Mod('T_stage1_A', Mod('T_stage1_A',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='1st Stage A', channel='1st Stage A',
main='main', main='main',
) )
Mod('T_stage2_A', Mod('T_stage2_A',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='2nd Stage A', channel='2nd Stage A',
main='main', main='main',
) )
Mod('T_stage1_B', Mod('T_stage1_B',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='1st Stage B', channel='1st Stage B',
main='main', main='main',
) )
Mod('T_stage2_B', Mod('T_stage2_B',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='2nd Stage B', channel='2nd Stage B',
main='main', main='main',
) )
Mod('T_top_A', Mod('T_top_A',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Inner Magnet A (Top)', channel='Inner Magnet A (Top)',
main='main', main='main',
) )
Mod('T_bottom_A', Mod('T_bottom_A',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Inner Magnet A (Bottom)', channel='Inner Magnet A (Bottom)',
main='main', main='main',
) )
Mod('T_top_B', Mod('T_top_B',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Inner Magnet B (Top)', channel='Inner Magnet B (Top)',
main='main', main='main',
) )
Mod('T_bottom_B', Mod('T_bottom_B',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Inner Magnet B (Bottom)', channel='Inner Magnet B (Bottom)',
main='main', main='main',
) )
Mod('T_Z_shim', Mod('T_Z_shim',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Z Shim Former', channel='Z Shim Former',
main='main', main='main',
) )
Mod('T_XY_shim', Mod('T_XY_shim',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='XY Shim Former', channel='XY Shim Former',
main='main', main='main',
) )
Mod('T_XY_vector', Mod('T_XY_vector',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='XY Vector Former', channel='XY Vector Former',
main='main', main='main',
) )
Mod('T_radiation_shield', Mod('T_radiation_shield',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Radiation Shield', channel='Radiation Shield',
main='main', main='main',
) )
Mod('T_persistent_joints', Mod('T_persistent_joints',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Persistent Joints', channel='Persistent Joints',
main='main', main='main',
) )
Mod('T_outer_A', Mod('T_outer_A',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Outer Magnet A', channel='Outer Magnet A',
main='main', main='main',
) )
Mod('T_outer_B', Mod('T_outer_B',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Outer Magnet B', channel='Outer Magnet B',
main='main', main='main',
) )
Mod('T_shim_B', Mod('T_shim_B',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Z Shim Former B', channel='Z Shim Former B',
main='main', main='main',
) )
Mod('T_bore_shield', Mod('T_bore_shield',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Bore Radiation Shield', channel='Bore Radiation Shield',
main='main', main='main',
) )
Mod('T_XYZ_shim', Mod('T_XYZ_shim',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='XYZ Shim Plate', channel='XYZ Shim Plate',
main='main', main='main',
) )
Mod('T_Z_shim_switch', Mod('T_Z_shim_switch',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Z Shim Switch', channel='Z Shim Switch',
main='main', main='main',
) )
Mod('T_main_switch', Mod('T_main_switch',
'frappy_psi.cryoltd.Temperature', 'frappy_psi.cryoltd.Temperature', '',
channel='Main Coil Switch', channel='Main Coil Switch',
main='main', main='main',
) )

View File

@ -4,7 +4,7 @@ Node('haakeuro.config.sea.psi.ch',
Mod('sea_main', Mod('sea_main',
'frappy_psi.sea.SeaClient', 'frappy_psi.sea.SeaClient',
'main sea connection for haakeuro.config', 'main sea connection for haakeuro.config',
config = 'haakeuro.config', config = 'haake.config',
service = 'main', service = 'main',
) )
Mod('th', Mod('th',

183
cfg/main/varioxb_cfg.py Normal file
View File

@ -0,0 +1,183 @@
Node('varioxb.psi.ch',
'VarioxB - 100 mm cryostat (not tested!)',
)
Mod('itc1',
'frappy_psi.mercury.IO',
'ITC for heat exchanger and pressures',
uri='mb11-ts:3001',
)
Mod('itc2',
'frappy_psi.mercury.IO',
'ITC for neck and nv heaters',
uri='mb11-ts:3002',
)
Mod('T_stat',
'frappy_psi.mercury.TemperatureAutoFlow',
'static heat exchanger temperature',
output_module='htr_stat',
needle_valve='p_stat',
slot='DB6.T1',
io='itc1',
tolerance=0.1,
)
Mod('htr_stat',
'frappy_psi.mercury.HeaterOutput',
'static heat exchanger heater',
slot='DB1.H1',
io='itc1',
)
Mod('p_stat',
'frappy_psi.mercury.PressureLoop',
'static needle valve pressure',
output_module='pos_stat',
settling_time=60.0,
slot='DB5.P1',
io='itc1',
tolerance=1.0,
value=Param(
unit='mbar_flow',
),
)
Mod('pos_stat',
'frappy_psi.mercury.ValvePos',
'static needle valve position',
slot='DB5.P1,DB3.G1',
io='itc1',
)
Mod('T_dyn',
'frappy_psi.mercury.TemperatureAutoFlow',
'dynamic heat exchanger temperature',
output_module='htr_dyn',
needle_valve='p_dyn',
slot='DB7.T1',
io='itc1',
tolerance=0.1,
)
Mod('htr_dyn',
'frappy_psi.mercury.HeaterOutput',
'dynamic heat exchanger heater',
slot='DB2.H1',
io='itc1',
)
Mod('p_dyn',
'frappy_psi.mercury.PressureLoop',
'dynamic needle valve pressure',
output_module='pos_dyn',
settling_time=60.0,
slot='DB8.P1',
io='itc1',
tolerance=1.0,
value=Param(
unit='mbar_flow',
),
)
Mod('pos_dyn',
'frappy_psi.mercury.ValvePos',
'dynamic needle valve position',
slot='DB8.P1,DB4.G1',
io='itc1',
)
Mod('lev',
'frappy_psi.mercury.HeLevel',
'LHe level',
slot='DB1.L1',
io='ips',
)
Mod('n2lev',
'frappy_psi.mercury.N2Level',
'LN2 level',
slot='DB1.L1',
io='ips',
)
Mod('T_neck1',
'frappy_psi.mercury.TemperatureLoop',
'neck heater 1 temperature',
output_module='htr_neck1',
slot='MB1.T1',
io='itc2',
tolerance=1.0,
)
Mod('htr_neck1',
'frappy_psi.mercury.HeaterOutput',
'neck heater 1 power',
slot='MB0.H1',
io='itc2',
)
Mod('T_neck2',
'frappy_psi.mercury.TemperatureLoop',
'neck heater 2 temperature',
output_module='htr_neck2',
slot='DB6.T1',
io='itc2',
tolerance=1.0,
)
Mod('htr_neck2',
'frappy_psi.mercury.HeaterOutput',
'neck heater 2 power',
slot='DB1.H1',
io='itc2',
)
Mod('T_nvs',
'frappy_psi.mercury.TemperatureLoop',
'static needle valve temperature',
output_module='htr_nvs',
slot='DB7.T1',
io='itc2',
tolerance=0.1,
)
Mod('htr_nvs',
'frappy_psi.mercury.HeaterOutput',
'static needle valve heater power',
slot='DB2.H1',
io='itc2',
)
Mod('T_nvd',
'frappy_psi.mercury.TemperatureLoop',
'dynamic needle valve heater temperature',
output_module='htr_nvd',
slot='DB8.T1',
io='itc2',
tolerance=0.1,
)
Mod('htr_nvd',
'frappy_psi.mercury.HeaterOutput',
'dynamic needle valve heater power',
slot='DB3.H1',
io='itc2',
)
Mod('om_io',
'frappy_psi.phytron.PhytronIO',
'dom motor IO',
uri='mb11-ts.psi.ch:3004',
)
Mod('om',
'frappy_psi.phytron.Motor',
'stick rotation, typically used for omega',
io='om_io',
target_min=-180,
target_max=360,
encoder_mode='NO',
target=Param(min=-180, max=360)
)

View File

@ -1,25 +0,0 @@
# error creating tt
# error creating nv
Node('ori1.psi.ch',
'ori1 over SEA',
interface='tcp://10767',
)
Mod('seaconn',
'frappy_psi.sea.SeaClient',
'a SEA connection',
)
Mod('tt',
'frappy_psi.sea.SeaDrivable',
io='seaconn',
json_descr='tt.ori1.config',
remote_paths='.',
)
Mod('nv',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='nv.ori1.config',
remote_paths='.',
)

View File

@ -1,153 +0,0 @@
# error creating tt
# error creating nv
# error creating ln2fill
# error creating hefill
# error creating tcoil
# error creating table
# error creating lnv
# error creating lpr
# error creating lambdawatch
# error creating ts
# error creating treg
# error creating tmon
# error creating sorb
# error creating ultrasound
# error creating fn
# error creating mirror
# error creating f
# error creating pars
Node('ma11_dil4_ultrasound_sr.psi.ch',
'ma11_dil4_ultrasound_sr over SEA',
interface='tcp://10767',
)
Mod('seaconn',
'frappy_psi.sea.SeaClient',
'a SEA connection',
)
Mod('tt',
'frappy_psi.sea.SeaDrivable',
io='seaconn',
json_descr='tt.ma11.config',
remote_paths='.',
)
Mod('nv',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='nv.ma11.config',
remote_paths='.',
)
Mod('ln2fill',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='ln2fill.ma11.config',
remote_paths='.',
)
Mod('hefill',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='hefill.ma11.config',
remote_paths='.',
)
Mod('tcoil',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tcoil.ma11.config',
remote_paths='.',
)
Mod('table',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='table.ma11.config',
remote_paths='.',
)
Mod('lnv',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='lnv.ma11.config',
remote_paths='.',
)
Mod('lpr',
'frappy_psi.sea.SeaDrivable',
io='seaconn',
json_descr='lpr.ma11.config',
remote_paths='.',
)
Mod('lambdawatch',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='lambdawatch.ma11.config',
remote_paths='.',
)
Mod('ts',
'frappy_psi.sea.SeaDrivable',
io='seaconn',
json_descr='ts.dil4.stick',
remote_paths='.',
)
Mod('treg',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='treg.dil4.stick',
remote_paths='.',
)
Mod('tmon',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tmon.dil4.stick',
remote_paths='.',
)
Mod('sorb',
'frappy_psi.sea.SeaDrivable',
io='seaconn',
json_descr='sorb.dil4.stick',
remote_paths='.',
)
Mod('ultrasound',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='ultrasound.ultrasound.addon',
remote_paths='.',
)
Mod('fn',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='fn.ultrasound.addon',
remote_paths='.',
)
Mod('mirror',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='mirror.ultrasound.addon',
remote_paths='.',
)
Mod('f',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='f.ultrasound.addon',
remote_paths='.',
)
Mod('pars',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='pars.ultrasound.addon',
remote_paths='.',
)

View File

@ -1,81 +0,0 @@
# error creating tvs
# error creating tvd
# error creating pstat
# error creating pdyn
# error creating tneck1
# error creating tneck2
# error creating tnvs
# error creating tnvd
# error creating ts
Node('varioxB_vb.psi.ch',
'varioxB_vb over SEA',
interface='tcp://10767',
)
Mod('seaconn',
'frappy_psi.sea.SeaClient',
'a SEA connection',
)
Mod('tvs',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tvs.varioxB.config',
remote_paths='.',
)
Mod('tvd',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tvd.varioxB.config',
remote_paths='.',
)
Mod('pstat',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='pstat.varioxB.config',
remote_paths='.',
)
Mod('pdyn',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='pdyn.varioxB.config',
remote_paths='.',
)
Mod('tneck1',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tneck1.varioxB.config',
remote_paths='.',
)
Mod('tneck2',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tneck2.varioxB.config',
remote_paths='.',
)
Mod('tnvs',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tnvs.varioxB.config',
remote_paths='.',
)
Mod('tnvd',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tnvd.varioxB.config',
remote_paths='.',
)
Mod('ts',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='ts.vb.stick',
remote_paths='.',
)

View File

@ -0,0 +1,160 @@
{"th": {"base": "/th", "params": [
{"path": "", "type": "float", "readonly": false, "cmd": "run th", "kids": 26},
{"path": "unit", "type": "text", "readonly": false, "cmd": "th unit", "visibility": 3},
{"path": "t2", "type": "float"},
{"path": "set", "type": "float"},
{"path": "running", "type": "int", "readonly": false, "cmd": "th running", "visibility": 3},
{"path": "extcontrol", "type": "int", "readonly": false, "cmd": "th extcontrol", "visibility": 3},
{"path": "relais", "type": "int", "visibility": 3},
{"path": "overtemp", "type": "int", "visibility": 3},
{"path": "lowlevel", "type": "int", "visibility": 3},
{"path": "pumpalarm", "type": "int", "visibility": 3},
{"path": "externalarm", "type": "int", "visibility": 3},
{"path": "coolalarm", "type": "int", "visibility": 3},
{"path": "sensor1alarm", "type": "int", "visibility": 3},
{"path": "sensor2alarm", "type": "int", "visibility": 3},
{"path": "reset", "type": "int", "readonly": false, "cmd": "th reset", "visibility": 3},
{"path": "with2sensors", "type": "int", "readonly": false, "cmd": "th with2sensors", "visibility": 3},
{"path": "upperLimit", "type": "float", "readonly": false, "cmd": "th upperLimit"},
{"path": "lowerLimit", "type": "float", "readonly": false, "cmd": "th lowerLimit"},
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "th tolerance"},
{"path": "maxwait", "type": "int", "readonly": false, "cmd": "th maxwait"},
{"path": "settle", "type": "int", "readonly": false, "cmd": "th settle"},
{"path": "targetValue", "type": "float"},
{"path": "is_running", "type": "int", "visibility": 3},
{"path": "verbose", "type": "int", "readonly": false, "cmd": "th verbose", "visibility": 3},
{"path": "driver", "type": "text", "visibility": 3},
{"path": "creationCmd", "type": "text", "visibility": 3},
{"path": "status", "type": "text", "readonly": false, "cmd": "th status"}]},
"te": {"base": "/te", "params": [
{"path": "", "type": "float", "readonly": false, "cmd": "run te", "kids": 30},
{"path": "unit", "type": "text", "readonly": false, "cmd": "te unit", "visibility": 3},
{"path": "mode", "type": "int", "readonly": false, "cmd": "te mode"},
{"path": "model", "type": "text", "visibility": 3},
{"path": "pbPow", "type": "float", "visibility": 3},
{"path": "pbMin", "type": "float", "visibility": 3},
{"path": "pbScl", "type": "float", "visibility": 3},
{"path": "output", "type": "float"},
{"path": "position", "type": "float", "readonly": false, "cmd": "te position"},
{"path": "asymmetry", "type": "float", "readonly": false, "cmd": "te asymmetry", "visibility": 3},
{"path": "range", "type": "float", "readonly": false, "cmd": "te range", "visibility": 3},
{"path": "set", "type": "float", "readonly": false, "cmd": "te set"},
{"path": "rdonly", "type": "int", "readonly": false, "cmd": "te rdonly", "visibility": 3},
{"path": "task", "type": "text", "readonly": false, "cmd": "te task"},
{"path": "upperLimit", "type": "float", "readonly": false, "cmd": "te upperLimit"},
{"path": "lowerLimit", "type": "float", "readonly": false, "cmd": "te lowerLimit", "visibility": 3},
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "te tolerance"},
{"path": "maxwait", "type": "int", "readonly": false, "cmd": "te maxwait"},
{"path": "settle", "type": "int", "readonly": false, "cmd": "te settle"},
{"path": "targetValue", "type": "float"},
{"path": "is_running", "type": "int", "visibility": 3},
{"path": "verbose", "type": "int", "readonly": false, "cmd": "te verbose", "visibility": 3},
{"path": "driver", "type": "text", "visibility": 3},
{"path": "creationCmd", "type": "text", "visibility": 3},
{"path": "status", "type": "text", "readonly": false, "cmd": "te status"},
{"path": "pb", "type": "float", "readonly": false, "cmd": "te pb"},
{"path": "ti", "type": "float", "readonly": false, "cmd": "te ti"},
{"path": "td", "type": "float", "readonly": false, "cmd": "te td"},
{"path": "manual", "type": "float", "readonly": false, "cmd": "te manual"},
{"path": "rate", "type": "float", "readonly": false, "cmd": "te rate"},
{"path": "workset", "type": "float", "readonly": false, "cmd": "te workset"}]},
"cc": {"base": "/cc", "params": [
{"path": "", "type": "bool", "kids": 96},
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
{"path": "status", "type": "text", "visibility": 3},
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
{"path": "fav", "type": "bool", "readonly": false, "cmd": "cc fav"},
{"path": "f", "type": "float", "visibility": 3},
{"path": "fs", "type": "enum", "enum": {"ok": 0, "no_sens": 1}, "readonly": false, "cmd": "cc fs", "visibility": 3},
{"path": "mav", "type": "bool", "readonly": false, "cmd": "cc mav"},
{"path": "fm", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}, "visibility": 3},
{"path": "fa", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "offline": 3}, "readonly": false, "cmd": "cc fa", "visibility": 3},
{"path": "mp", "type": "float", "readonly": false, "cmd": "cc mp", "visibility": 3},
{"path": "msp", "type": "float", "visibility": 3},
{"path": "mmp", "type": "float", "visibility": 3},
{"path": "mc", "type": "float", "readonly": false, "cmd": "cc mc", "visibility": 3},
{"path": "mfc", "type": "float", "readonly": false, "cmd": "cc mfc", "visibility": 3},
{"path": "moc", "type": "float", "readonly": false, "cmd": "cc moc", "visibility": 3},
{"path": "mtc", "type": "float", "readonly": false, "cmd": "cc mtc", "visibility": 3},
{"path": "mtl", "type": "float", "visibility": 3},
{"path": "mft", "type": "float", "readonly": false, "cmd": "cc mft", "visibility": 3},
{"path": "mt", "type": "float", "visibility": 3},
{"path": "mo", "type": "float", "visibility": 3},
{"path": "mcr", "type": "float", "visibility": 3},
{"path": "mot", "type": "float", "visibility": 3},
{"path": "mw", "type": "float", "readonly": false, "cmd": "cc mw", "description": "correction pulse after automatic open", "visibility": 3},
{"path": "hav", "type": "bool", "readonly": false, "cmd": "cc hav"},
{"path": "h", "type": "float", "visibility": 3},
{"path": "hr", "type": "float", "visibility": 3},
{"path": "hc", "type": "float", "visibility": 3},
{"path": "hu", "type": "float", "visibility": 3},
{"path": "hh", "type": "float", "readonly": false, "cmd": "cc hh", "visibility": 3},
{"path": "hl", "type": "float", "readonly": false, "cmd": "cc hl", "visibility": 3},
{"path": "htf", "type": "float", "readonly": false, "cmd": "cc htf", "description": "meas. period in fast mode", "visibility": 3},
{"path": "hts", "type": "float", "readonly": false, "cmd": "cc hts", "description": "meas. period in slow mode", "visibility": 3},
{"path": "hd", "type": "float", "readonly": false, "cmd": "cc hd", "visibility": 3},
{"path": "hwr", "type": "float", "readonly": false, "cmd": "cc hwr", "visibility": 3},
{"path": "hem", "type": "float", "readonly": false, "cmd": "cc hem", "description": "sensor length in mm from top to empty pos.", "visibility": 3},
{"path": "hfu", "type": "float", "readonly": false, "cmd": "cc hfu", "description": "sensor length in mm from top to full pos.", "visibility": 3},
{"path": "hcd", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3, "manual": 7}, "readonly": false, "cmd": "cc hcd", "visibility": 3},
{"path": "hv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4}, "visibility": 3},
{"path": "hsf", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "ha", "type": "bool", "readonly": false, "cmd": "cc ha", "visibility": 3},
{"path": "hm", "type": "bool", "visibility": 3},
{"path": "hf", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "cc hf", "visibility": 3},
{"path": "hbe", "type": "bool", "readonly": false, "cmd": "cc hbe", "visibility": 3},
{"path": "hmf", "type": "float", "visibility": 3},
{"path": "hms", "type": "float", "visibility": 3},
{"path": "hit", "type": "float", "readonly": false, "cmd": "cc hit", "visibility": 3},
{"path": "hft", "type": "int", "readonly": false, "cmd": "cc hft", "visibility": 3},
{"path": "hea", "type": "enum", "enum": {"0": 0, "1": 1, "6": 6}, "readonly": false, "cmd": "cc hea"},
{"path": "hch", "type": "int", "readonly": false, "cmd": "cc hch", "visibility": 3},
{"path": "hwr0", "type": "float", "readonly": false, "cmd": "cc hwr0", "visibility": 3},
{"path": "hem0", "type": "float", "readonly": false, "cmd": "cc hem0", "description": "sensor length in mm from top to empty pos.", "visibility": 3},
{"path": "hfu0", "type": "float", "readonly": false, "cmd": "cc hfu0", "description": "sensor length in mm from top to full pos.", "visibility": 3},
{"path": "hd0", "type": "float", "readonly": false, "cmd": "cc hd0", "description": "external sensor drive current (mA)", "visibility": 3},
{"path": "h0", "type": "float", "visibility": 3},
{"path": "hs0", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h1", "type": "float", "visibility": 3},
{"path": "hs1", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h2", "type": "float", "visibility": 3},
{"path": "hs2", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h3", "type": "float", "visibility": 3},
{"path": "hs3", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h4", "type": "float", "visibility": 3},
{"path": "hs4", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h5", "type": "float", "visibility": 3},
{"path": "hs5", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "hfb", "type": "float", "visibility": 3},
{"path": "nav", "type": "bool", "readonly": false, "cmd": "cc nav"},
{"path": "nu", "type": "float", "visibility": 3},
{"path": "nl", "type": "float", "visibility": 3},
{"path": "nth", "type": "float", "readonly": false, "cmd": "cc nth", "visibility": 3},
{"path": "ntc", "type": "float", "readonly": false, "cmd": "cc ntc", "visibility": 3},
{"path": "ntm", "type": "float", "readonly": false, "cmd": "cc ntm", "visibility": 3},
{"path": "ns", "type": "enum", "enum": {"sens_ok": 0, "no_sens": 1, "short_circuit": 2, "upside_down": 3, "sens_warm": 4, "empty": 5}, "visibility": 3},
{"path": "na", "type": "bool", "readonly": false, "cmd": "cc na", "visibility": 3},
{"path": "nv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4, "boost": 5}, "visibility": 3},
{"path": "nc", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3}, "readonly": false, "cmd": "cc nc", "visibility": 3},
{"path": "nfb", "type": "float", "visibility": 3},
{"path": "cda", "type": "float"},
{"path": "cdb", "type": "float"},
{"path": "cba", "type": "float"},
{"path": "cbb", "type": "float"},
{"path": "cvs", "type": "int"},
{"path": "csp", "type": "int"},
{"path": "cdv", "type": "text", "readonly": false, "cmd": "cc cdv"},
{"path": "cic", "type": "text", "readonly": false, "cmd": "cc cic"},
{"path": "cin", "type": "text"},
{"path": "cds", "type": "enum", "enum": {"local": 0, "remote": 1, "loading": 2, "by_code": 3, "by_touch": 4}, "readonly": false, "cmd": "cc cds"},
{"path": "timing", "type": "bool", "readonly": false, "cmd": "cc timing"},
{"path": "tc", "type": "float", "visibility": 3},
{"path": "tn", "type": "float", "visibility": 3},
{"path": "th", "type": "float", "visibility": 3},
{"path": "tf", "type": "float", "visibility": 3},
{"path": "tm", "type": "float", "visibility": 3},
{"path": "tv", "type": "float", "visibility": 3},
{"path": "tq", "type": "float", "visibility": 3},
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]}}

160
cfg/sea/haake.config.json Normal file
View File

@ -0,0 +1,160 @@
{"th": {"base": "/th", "params": [
{"path": "", "type": "float", "readonly": false, "cmd": "run th", "kids": 26},
{"path": "unit", "type": "text", "readonly": false, "cmd": "th unit", "visibility": 3},
{"path": "t2", "type": "float"},
{"path": "set", "type": "float"},
{"path": "running", "type": "int", "readonly": false, "cmd": "th running", "visibility": 3},
{"path": "extcontrol", "type": "int", "readonly": false, "cmd": "th extcontrol", "visibility": 3},
{"path": "relais", "type": "int", "visibility": 3},
{"path": "overtemp", "type": "int", "visibility": 3},
{"path": "lowlevel", "type": "int", "visibility": 3},
{"path": "pumpalarm", "type": "int", "visibility": 3},
{"path": "externalarm", "type": "int", "visibility": 3},
{"path": "coolalarm", "type": "int", "visibility": 3},
{"path": "sensor1alarm", "type": "int", "visibility": 3},
{"path": "sensor2alarm", "type": "int", "visibility": 3},
{"path": "reset", "type": "int", "readonly": false, "cmd": "th reset", "visibility": 3},
{"path": "with2sensors", "type": "int", "readonly": false, "cmd": "th with2sensors", "visibility": 3},
{"path": "upperLimit", "type": "float", "readonly": false, "cmd": "th upperLimit"},
{"path": "lowerLimit", "type": "float", "readonly": false, "cmd": "th lowerLimit"},
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "th tolerance"},
{"path": "maxwait", "type": "int", "readonly": false, "cmd": "th maxwait"},
{"path": "settle", "type": "int", "readonly": false, "cmd": "th settle"},
{"path": "targetValue", "type": "float"},
{"path": "is_running", "type": "int", "visibility": 3},
{"path": "verbose", "type": "int", "readonly": false, "cmd": "th verbose", "visibility": 3},
{"path": "driver", "type": "text", "visibility": 3},
{"path": "creationCmd", "type": "text", "visibility": 3},
{"path": "status", "type": "text", "readonly": false, "cmd": "th status"}]},
"te": {"base": "/te", "params": [
{"path": "", "type": "float", "readonly": false, "cmd": "run te", "kids": 30},
{"path": "unit", "type": "text", "readonly": false, "cmd": "te unit", "visibility": 3},
{"path": "mode", "type": "int", "readonly": false, "cmd": "te mode"},
{"path": "model", "type": "text", "visibility": 3},
{"path": "pbPow", "type": "float", "visibility": 3},
{"path": "pbMin", "type": "float", "visibility": 3},
{"path": "pbScl", "type": "float", "visibility": 3},
{"path": "output", "type": "float"},
{"path": "position", "type": "float", "readonly": false, "cmd": "te position"},
{"path": "asymmetry", "type": "float", "readonly": false, "cmd": "te asymmetry", "visibility": 3},
{"path": "range", "type": "float", "readonly": false, "cmd": "te range", "visibility": 3},
{"path": "set", "type": "float", "readonly": false, "cmd": "te set"},
{"path": "rdonly", "type": "int", "readonly": false, "cmd": "te rdonly", "visibility": 3},
{"path": "task", "type": "text", "readonly": false, "cmd": "te task"},
{"path": "upperLimit", "type": "float", "readonly": false, "cmd": "te upperLimit"},
{"path": "lowerLimit", "type": "float", "readonly": false, "cmd": "te lowerLimit", "visibility": 3},
{"path": "tolerance", "type": "float", "readonly": false, "cmd": "te tolerance"},
{"path": "maxwait", "type": "int", "readonly": false, "cmd": "te maxwait"},
{"path": "settle", "type": "int", "readonly": false, "cmd": "te settle"},
{"path": "targetValue", "type": "float"},
{"path": "is_running", "type": "int", "visibility": 3},
{"path": "verbose", "type": "int", "readonly": false, "cmd": "te verbose", "visibility": 3},
{"path": "driver", "type": "text", "visibility": 3},
{"path": "creationCmd", "type": "text", "visibility": 3},
{"path": "status", "type": "text", "readonly": false, "cmd": "te status"},
{"path": "pb", "type": "float", "readonly": false, "cmd": "te pb"},
{"path": "ti", "type": "float", "readonly": false, "cmd": "te ti"},
{"path": "td", "type": "float", "readonly": false, "cmd": "te td"},
{"path": "manual", "type": "float", "readonly": false, "cmd": "te manual"},
{"path": "rate", "type": "float", "readonly": false, "cmd": "te rate"},
{"path": "workset", "type": "float", "readonly": false, "cmd": "te workset"}]},
"cc": {"base": "/cc", "params": [
{"path": "", "type": "bool", "kids": 96},
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
{"path": "status", "type": "text", "visibility": 3},
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
{"path": "fav", "type": "bool", "readonly": false, "cmd": "cc fav"},
{"path": "f", "type": "float", "visibility": 3},
{"path": "fs", "type": "enum", "enum": {"ok": 0, "no_sens": 1}, "readonly": false, "cmd": "cc fs", "visibility": 3},
{"path": "mav", "type": "bool", "readonly": false, "cmd": "cc mav"},
{"path": "fm", "type": "enum", "enum": {"idle": 0, "opening": 1, "closing": 2, "opened": 3, "closed": 4, "no_motor": 5}, "visibility": 3},
{"path": "fa", "type": "enum", "enum": {"fixed": 0, "controlled": 1, "automatic": 2, "offline": 3}, "readonly": false, "cmd": "cc fa", "visibility": 3},
{"path": "mp", "type": "float", "readonly": false, "cmd": "cc mp", "visibility": 3},
{"path": "msp", "type": "float", "visibility": 3},
{"path": "mmp", "type": "float", "visibility": 3},
{"path": "mc", "type": "float", "readonly": false, "cmd": "cc mc", "visibility": 3},
{"path": "mfc", "type": "float", "readonly": false, "cmd": "cc mfc", "visibility": 3},
{"path": "moc", "type": "float", "readonly": false, "cmd": "cc moc", "visibility": 3},
{"path": "mtc", "type": "float", "readonly": false, "cmd": "cc mtc", "visibility": 3},
{"path": "mtl", "type": "float", "visibility": 3},
{"path": "mft", "type": "float", "readonly": false, "cmd": "cc mft", "visibility": 3},
{"path": "mt", "type": "float", "visibility": 3},
{"path": "mo", "type": "float", "visibility": 3},
{"path": "mcr", "type": "float", "visibility": 3},
{"path": "mot", "type": "float", "visibility": 3},
{"path": "mw", "type": "float", "readonly": false, "cmd": "cc mw", "description": "correction pulse after automatic open", "visibility": 3},
{"path": "hav", "type": "bool", "readonly": false, "cmd": "cc hav"},
{"path": "h", "type": "float", "visibility": 3},
{"path": "hr", "type": "float", "visibility": 3},
{"path": "hc", "type": "float", "visibility": 3},
{"path": "hu", "type": "float", "visibility": 3},
{"path": "hh", "type": "float", "readonly": false, "cmd": "cc hh", "visibility": 3},
{"path": "hl", "type": "float", "readonly": false, "cmd": "cc hl", "visibility": 3},
{"path": "htf", "type": "float", "readonly": false, "cmd": "cc htf", "description": "meas. period in fast mode", "visibility": 3},
{"path": "hts", "type": "float", "readonly": false, "cmd": "cc hts", "description": "meas. period in slow mode", "visibility": 3},
{"path": "hd", "type": "float", "readonly": false, "cmd": "cc hd", "visibility": 3},
{"path": "hwr", "type": "float", "readonly": false, "cmd": "cc hwr", "visibility": 3},
{"path": "hem", "type": "float", "readonly": false, "cmd": "cc hem", "description": "sensor length in mm from top to empty pos.", "visibility": 3},
{"path": "hfu", "type": "float", "readonly": false, "cmd": "cc hfu", "description": "sensor length in mm from top to full pos.", "visibility": 3},
{"path": "hcd", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3, "manual": 7}, "readonly": false, "cmd": "cc hcd", "visibility": 3},
{"path": "hv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4}, "visibility": 3},
{"path": "hsf", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "ha", "type": "bool", "readonly": false, "cmd": "cc ha", "visibility": 3},
{"path": "hm", "type": "bool", "visibility": 3},
{"path": "hf", "type": "enum", "enum": {"slow": 0, "fast": 1}, "readonly": false, "cmd": "cc hf", "visibility": 3},
{"path": "hbe", "type": "bool", "readonly": false, "cmd": "cc hbe", "visibility": 3},
{"path": "hmf", "type": "float", "visibility": 3},
{"path": "hms", "type": "float", "visibility": 3},
{"path": "hit", "type": "float", "readonly": false, "cmd": "cc hit", "visibility": 3},
{"path": "hft", "type": "int", "readonly": false, "cmd": "cc hft", "visibility": 3},
{"path": "hea", "type": "enum", "enum": {"0": 0, "1": 1, "6": 6}, "readonly": false, "cmd": "cc hea"},
{"path": "hch", "type": "int", "readonly": false, "cmd": "cc hch", "visibility": 3},
{"path": "hwr0", "type": "float", "readonly": false, "cmd": "cc hwr0", "visibility": 3},
{"path": "hem0", "type": "float", "readonly": false, "cmd": "cc hem0", "description": "sensor length in mm from top to empty pos.", "visibility": 3},
{"path": "hfu0", "type": "float", "readonly": false, "cmd": "cc hfu0", "description": "sensor length in mm from top to full pos.", "visibility": 3},
{"path": "hd0", "type": "float", "readonly": false, "cmd": "cc hd0", "description": "external sensor drive current (mA)", "visibility": 3},
{"path": "h0", "type": "float", "visibility": 3},
{"path": "hs0", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h1", "type": "float", "visibility": 3},
{"path": "hs1", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h2", "type": "float", "visibility": 3},
{"path": "hs2", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h3", "type": "float", "visibility": 3},
{"path": "hs3", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h4", "type": "float", "visibility": 3},
{"path": "hs4", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "h5", "type": "float", "visibility": 3},
{"path": "hs5", "type": "enum", "enum": {"sens_ok": 0, "sens_warm": 1, "no_sens": 2, "timeout": 3, "not_yet_read": 4, "disabled": 5}, "visibility": 3},
{"path": "hfb", "type": "float", "visibility": 3},
{"path": "nav", "type": "bool", "readonly": false, "cmd": "cc nav"},
{"path": "nu", "type": "float", "visibility": 3},
{"path": "nl", "type": "float", "visibility": 3},
{"path": "nth", "type": "float", "readonly": false, "cmd": "cc nth", "visibility": 3},
{"path": "ntc", "type": "float", "readonly": false, "cmd": "cc ntc", "visibility": 3},
{"path": "ntm", "type": "float", "readonly": false, "cmd": "cc ntm", "visibility": 3},
{"path": "ns", "type": "enum", "enum": {"sens_ok": 0, "no_sens": 1, "short_circuit": 2, "upside_down": 3, "sens_warm": 4, "empty": 5}, "visibility": 3},
{"path": "na", "type": "bool", "readonly": false, "cmd": "cc na", "visibility": 3},
{"path": "nv", "type": "enum", "enum": {"fill_valve_off": 0, "filling": 1, "no_fill_valve": 2, "timeout": 3, "timeout1": 4, "boost": 5}, "visibility": 3},
{"path": "nc", "type": "enum", "enum": {"stop": 0, "fill": 1, "off": 2, "auto": 3}, "readonly": false, "cmd": "cc nc", "visibility": 3},
{"path": "nfb", "type": "float", "visibility": 3},
{"path": "cda", "type": "float"},
{"path": "cdb", "type": "float"},
{"path": "cba", "type": "float"},
{"path": "cbb", "type": "float"},
{"path": "cvs", "type": "int"},
{"path": "csp", "type": "int"},
{"path": "cdv", "type": "text", "readonly": false, "cmd": "cc cdv"},
{"path": "cic", "type": "text", "readonly": false, "cmd": "cc cic"},
{"path": "cin", "type": "text"},
{"path": "cds", "type": "enum", "enum": {"local": 0, "remote": 1, "loading": 2, "by_code": 3, "by_touch": 4}, "readonly": false, "cmd": "cc cds"},
{"path": "timing", "type": "bool", "readonly": false, "cmd": "cc timing"},
{"path": "tc", "type": "float", "visibility": 3},
{"path": "tn", "type": "float", "visibility": 3},
{"path": "th", "type": "float", "visibility": 3},
{"path": "tf", "type": "float", "visibility": 3},
{"path": "tm", "type": "float", "visibility": 3},
{"path": "tv", "type": "float", "visibility": 3},
{"path": "tq", "type": "float", "visibility": 3},
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]}}

56
cfg/sea/mb11.config.json Normal file
View File

@ -0,0 +1,56 @@
{"hepump": {"base": "/hepump", "params": [
{"path": "", "type": "enum", "enum": {"xds35_auto": 0, "xds35_manual": 1, "sv65": 2, "other": 3, "no": -1}, "readonly": false, "cmd": "hepump", "description": "xds35: scroll pump, sv65: leybold", "kids": 10},
{"path": "send", "type": "text", "readonly": false, "cmd": "hepump send", "visibility": 3},
{"path": "status", "type": "text", "visibility": 3},
{"path": "running", "type": "bool", "readonly": false, "cmd": "hepump running", "visibility": 3},
{"path": "eco", "type": "bool", "readonly": false, "cmd": "hepump eco", "visibility": 3},
{"path": "auto", "type": "bool", "readonly": false, "cmd": "hepump auto", "visibility": 3},
{"path": "valve", "type": "enum", "enum": {"closed": 0, "closing": 1, "opening": 2, "opened": 3, "undefined": 4}, "readonly": false, "cmd": "hepump valve", "visibility": 3},
{"path": "eco_t_lim", "type": "float", "readonly": false, "cmd": "hepump eco_t_lim", "description": "switch off eco mode when T_set < eco_t_lim and T < eco_t_lim * 2", "visibility": 3},
{"path": "calib", "type": "float", "readonly": false, "cmd": "hepump calib", "visibility": 3},
{"path": "health", "type": "float"}]},
"hemot": {"base": "/hepump/hemot", "params": [
{"path": "", "type": "float", "readonly": false, "cmd": "run hemot", "visibility": 3, "kids": 30},
{"path": "send", "type": "text", "readonly": false, "cmd": "hemot send", "visibility": 3},
{"path": "status", "type": "text", "visibility": 3},
{"path": "is_running", "type": "int", "readonly": false, "cmd": "hemot is_running", "visibility": 3},
{"path": "pos", "type": "float"},
{"path": "encoder", "type": "float"},
{"path": "zero", "type": "float", "readonly": false, "cmd": "hemot zero"},
{"path": "lowerlimit", "type": "float", "readonly": false, "cmd": "hemot lowerlimit"},
{"path": "upperlimit", "type": "float", "readonly": false, "cmd": "hemot upperlimit"},
{"path": "disablelimits", "type": "bool", "readonly": false, "cmd": "hemot disablelimits"},
{"path": "verbose", "type": "bool", "readonly": false, "cmd": "hemot verbose"},
{"path": "target", "type": "float"},
{"path": "runstate", "type": "enum", "enum": {"idle": 0, "running": 1, "finished": 2, "error": 3}},
{"path": "precision", "type": "float", "readonly": false, "cmd": "hemot precision"},
{"path": "maxencdif", "type": "float", "readonly": false, "cmd": "hemot maxencdif"},
{"path": "id", "type": "float", "readonly": false, "cmd": "hemot id"},
{"path": "pump_number", "type": "float", "readonly": false, "cmd": "hemot pump_number"},
{"path": "init", "type": "float", "readonly": false, "cmd": "hemot init"},
{"path": "maxspeed", "type": "float", "readonly": false, "cmd": "hemot maxspeed"},
{"path": "acceleration", "type": "float", "readonly": false, "cmd": "hemot acceleration"},
{"path": "maxcurrent", "type": "float", "readonly": false, "cmd": "hemot maxcurrent"},
{"path": "standbycurrent", "type": "float", "readonly": false, "cmd": "hemot standbycurrent"},
{"path": "freewheeling", "type": "bool", "readonly": false, "cmd": "hemot freewheeling"},
{"path": "output0", "type": "bool", "readonly": false, "cmd": "hemot output0"},
{"path": "output1", "type": "bool", "readonly": false, "cmd": "hemot output1"},
{"path": "input3", "type": "bool"},
{"path": "pullup", "type": "float", "readonly": false, "cmd": "hemot pullup"},
{"path": "nopumpfeedback", "type": "bool", "readonly": false, "cmd": "hemot nopumpfeedback"},
{"path": "eeprom", "type": "enum", "enum": {"ok": 0, "dirty": 1, "save": 2, "load": 3}, "readonly": false, "cmd": "hemot eeprom"},
{"path": "customadr", "type": "text", "readonly": false, "cmd": "hemot customadr"},
{"path": "custompar", "type": "float", "readonly": false, "cmd": "hemot custompar"}]}
"nvflow": {"base": "/nvflow", "params": [
{"path": "", "type": "float", "kids": 7},
{"path": "send", "type": "text", "readonly": false, "cmd": "nvflow send", "visibility": 3},
{"path": "status", "type": "text", "visibility": 3},
{"path": "stddev", "type": "float"},
{"path": "nsamples", "type": "int", "readonly": false, "cmd": "nvflow nsamples"},
{"path": "offset", "type": "float", "readonly": false, "cmd": "nvflow offset"},
{"path": "scale", "type": "float", "readonly": false, "cmd": "nvflow scale"},
{"path": "save", "type": "bool", "readonly": false, "cmd": "nvflow save", "description": "unchecked: current calib is not saved. set checked: save calib"}]},
}

View File

@ -1,218 +0,0 @@
Node('ccr12',
'''[sim] CCR12 box of MLZ Sample environment group
Contains a Lakeshore 336 and an PLC controlling the compressor
and some valves.
This is how we use it now.''',
interface='tcp://10767',
)
Mod('T_ccr12',
'frappy.simulation.SimDrivable',
description='Main temperature control node of CCR12.\n\nSwitches between regulation on stick and regulation on tube depending on temperature requested.\nMay also pump gas for higher temperatures, if configured.\n\nNote: in nicos this is handled by its own class which manages T_ccr12_stick and T_ccr12_tube.\nin this simulation this module is isolated.',
extra_params=['ramp'],
ramp=Param(
datatype=FloatRange(unit='K/min', minval=0.0, maxval=60.0),
default=60.0,
),
value=Param(
datatype=FloatRange(unit='K', minval=0.0, maxval=600.0),
default=300.0,
),
target=Param(
datatype=FloatRange(unit='K', minval=0.0, maxval=600.0),
default=300.0,
),
meaning=('temperature_regulation', 20),
)
Mod('T_ccr12_stick',
'frappy.simulation.SimDrivable',
description='Temperature regulation for the sample stick in ccr12.',
extra_params=['ramp'],
ramp=Param(
datatype=FloatRange(unit='K/min', minval=0.0, maxval=60.0),
default=60.0,
),
value=Param(
datatype=FloatRange(unit='K', minval=0.0, maxval=600.0),
default=300.0,
),
target=Param(
datatype=FloatRange(unit='K', minval=0.0, maxval=600.0),
default=300.0,
),
meaning=('temperature_regulation', 15),
)
Mod('T_ccr12_tube',
'frappy.simulation.SimDrivable',
description='Temperature regulation for the tube of ccr12.',
extra_params=['ramp'],
ramp=Param(
datatype=FloatRange(unit='K/min', minval=0.0, maxval=60.0),
default=60.0,
),
value=Param(
datatype=FloatRange(unit='K', minval=0.0, maxval=600.0),
default=300.0,
),
target=Param(
datatype=FloatRange(unit='K', minval=0.0, maxval=600.0),
default=300.0,
),
meaning=('temperature_regulation', 10),
)
Mod('T_ccr12_A',
'frappy.simulation.SimReadable',
description='(optional) Sample temperature sensor.',
value=Param(
datatype=FloatRange(unit='K'),
default=300.0,
),
meaning=('temperature', 9),
)
Mod('T_ccr12_B',
'frappy.simulation.SimReadable',
description='(regulation) temperature sensor on stick.',
value=Param(
datatype=FloatRange(unit='K'),
default=300.0,
),
meaning=('temperature', 10),
)
Mod('T_ccr12_C',
'frappy.simulation.SimReadable',
description='Temperature at the coldhead.',
value=Param(
datatype=FloatRange(unit='K'),
default=70.0,
),
meaning=('temperature', 1),
)
Mod('T_ccr12_D',
'frappy.simulation.SimReadable',
description='(regulation) temperature at coupling to stick.',
value=Param(
datatype=FloatRange(unit='K'),
default=80.0,
),
meaning=('temperature', 2),
)
Mod('ccr12_pressure_regulate',
'frappy.simulation.SimWritable',
description='Selects on which Sensor the pressure regulation works, or switches it off.',
visibility='expert',
value=Param(
datatype=EnumType('', off=0, p1=1, p2=2),
default='off',
),
target=Param(
datatype=EnumType('', off=0, p1=1, p2=2),
default='off',
),
)
Mod('ccr12_compressor',
'frappy.simulation.SimDrivable',
description='Switches the compressor for the cooling stage on or off.\n\nNote: This should always be on, except for fast heatup for sample change.',
value=Param(
datatype=EnumType('', off=0, on=1),
default='on',
),
target=Param(
datatype=EnumType('', off=0, on=1),
default='on',
),
)
Mod('ccr12_gas_switch',
'frappy.simulation.SimWritable',
description='Switches the gas inlet on or off.\n\nnote: in reality this switches itself off after 15min.\nnote: in reality this is interlocked with ccr12_vacuum_switch, only one can be on!\nnote: in this simulation this module is isolated.',
value=Param(
datatype=EnumType('', off=0, on=1),
default='off',
),
target=Param(
datatype=EnumType('', off=0, on=1),
default='off',
),
)
Mod('ccr12_vacuum_switch',
'frappy.simulation.SimWritable',
description='Switches the vacuum pumping valve on or off.\n\nnote: in reality this is interlocked with ccr12_gas_switch, only one can be on!\nnote: in this simulation this module is isolated.',
value=Param(
datatype=EnumType('', off=0, on=1),
default='off',
),
target=Param(
datatype=EnumType('', off=0, on=1),
default='off',
),
)
Mod('ccr12_p1',
'frappy.simulation.SimReadable',
description='Default pressure Sensor, linear scale 0..1000mbar',
value=Param(
datatype=FloatRange(unit='mbar'),
default=999.0,
),
)
Mod('ccr12_p2',
'frappy.simulation.SimReadable',
description='Auxillary pressure Sensor.',
value=Param(
datatype=FloatRange(unit='mbar'),
default=1e-06,
),
)
Mod('ccr12_curve_p2',
'frappy.simulation.SimWritable',
description='Curve for Aux pressure Sensor p2',
visibility='expert',
value=Param(
default='TTR100',
datatype=EnumType('', 0..10V=0, default=1, 0..9V=2, DI200=3, DI2000=4, TTR100=7, PTR90=8, PTR225/PTR237=9, ITR90=10, ITR100 curve D=11, ITR100 curve 2=12, ITR100 curve 3=13, ITR100 curve 4=14, ITR100 curve 5=15, ITR100 curve 6=16, ITR100 curve 7=17, ITR100 curve 8=18, ITR100 curve 9=19, ITR100 curve A=20, CMR361=21, CMR362=22, CMR363=23, CMR364=24, CMR365=25),
),
target=Param(
datatype=EnumType('', 0..10V=0, default=1, 0..9V=2, DI200=3, DI2000=4, TTR100=7, PTR90=8, PTR225/PTR237=9, ITR90=10, ITR100 curve D=11, ITR100 curve 2=12, ITR100 curve 3=13, ITR100 curve 4=14, ITR100 curve 5=15, ITR100 curve 6=16, ITR100 curve 7=17, ITR100 curve 8=18, ITR100 curve 9=19, ITR100 curve A=20, CMR361=21, CMR362=22, CMR363=23, CMR364=24, CMR365=25),
),
)
Mod('ccr12_p1_limits',
'frappy.simulation.SimWritable',
description='Limits for pressure regulation in P1.',
visibility='expert',
value=Param(
datatype=TupleOf(FloatRange(unit='mbar', minval=0.0, maxval=1000.0), FloatRange(unit='mbar', minval=0.0, maxval=1000.0)),
default=(0.0, 10.0),
),
target=Param(
datatype=TupleOf(FloatRange(unit='mbar', minval=0.0, maxval=1000.0), FloatRange(unit='mbar', minval=0.0, maxval=1000.0)),
default=(0.0, 10.0),
),
)
Mod('ccr12_p2_limits',
'frappy.simulation.SimWritable',
description='Limits for pressure regulation in P2.',
visibility='expert',
value=Param(
datatype=TupleOf(FloatRange(unit='mbar', minval=0.0, maxval=1000.0), FloatRange(unit='mbar', minval=0.0, maxval=1000.0)),
default=(1e-05, 0.001),
),
target=Param(
datatype=TupleOf(FloatRange(unit='mbar', minval=0.0, maxval=1000.0), FloatRange(unit='mbar', minval=0.0, maxval=1000.0)),
default=(1e-05, 0.001),
),
)

View File

@ -1,100 +0,0 @@
Node('stressihtf2',
'''[sim] Stressihtf2 box of MLZ Sample environment group
Controls an High Temperature Furnace with an Eurotherm and an PLC controlling some valves and checking cooling water.''',
interface='tcp://10767',
)
Mod('T_stressihtf2',
'frappy.simulation.SimDrivable',
description='Main temperature control node of Stressihtf2.',
value=Param(
datatype=FloatRange(unit='degC', minval=0.0),
default=20.0,
),
target=Param(
datatype=FloatRange(unit='degC', minval=0.0, maxval=2000.0),
default=20.0,
),
extra_params=['ramp', 'regulationmode', 'abslimits', 'userlimits'],
ramp=Param(
datatype=FloatRange(unit='K/min', minval=0.0, maxval=600.0),
description='target ramping speed in K/min.',
default=60.0,
),
abslimits=Param(
datatype=TupleOf(FloatRange(unit='degC', minval=0.0, maxval=2000.0), FloatRange(unit='degC', minval=0.0, maxval=2000.0)),
default=(0.0, 2000.0),
description='currently active absolute limits for the setpoint. depend on the regulationmode parameter (both/stick->0..600, tube->0..300K).',
),
userlimits=Param(
datatype=TupleOf(FloatRange(unit='degC', minval=0.0, maxval=2000.0), FloatRange(unit='degC', minval=0.0, maxval=2000.0)),
default=(0.0, 300.0),
description='current user set limits for the setpoint. must be inside abslimits.',
readonly=False,
),
meaning=('temperature_regulation', 10),
)
Mod('T_stressihtf2_sample',
'frappy.simulation.SimReadable',
description='(optional) Sample temperature sensor.',
visibility='expert',
value=Param(
default=300.0,
datatype=FloatRange(unit='degC', minval=0.0),
),
meaning=('temperature', 9),
)
Mod('stressihtf2_n2',
'frappy.simulation.SimWritable',
description='Switches the N2 gas inlet on or off.',
visibility='expert',
value=Param(
default='off',
datatype=EnumType('', off=0, on=1),
),
target=Param(
datatype=EnumType('', off=0, on=1),
default='off',
),
)
Mod('stressihtf2_he',
'frappy.simulation.SimWritable',
description='Switches the He gas inlet on or off.',
visibility='expert',
value=Param(
default='off',
datatype=EnumType('', off=0, on=1),
),
target=Param(
datatype=EnumType('', off=0, on=1),
default='off',
),
)
Mod('stressihtf2_lamps',
'frappy.simulation.SimWritable',
description='Switches the heating lamps on or off.',
visibility='expert',
value=Param(
default='on',
datatype=EnumType('', off=0, on=1),
),
target=Param(
datatype=EnumType('', off=0, on=1),
default='on',
),
)
Mod('stressihtf2_water_ok',
'frappy.simulation.SimReadable',
description='Readout of the cooling water state.',
visibility='expert',
value=Param(
default='ok',
datatype=EnumType('', failed=0, ok=1),
),
)

View File

@ -46,7 +46,7 @@ Mod('res',
), ),
value=Param( value=Param(
default=99.0, default=99.0,
datatype=FloatRange(unit='Ohm'), unit='Ohm',
), ),
) )

View File

@ -50,6 +50,7 @@ Mod('res',
Mod('T', Mod('T',
'frappy_psi.softcal.Sensor', 'frappy_psi.softcal.Sensor',
'sample T',
rawsensor='res', rawsensor='res',
calib='X132254', calib='X132254',
value=Param( value=Param(

View File

@ -1,73 +0,0 @@
# error creating tvs
# error creating tvd
# error creating pstat
# error creating pdyn
# error creating tneck1
# error creating tneck2
# error creating tnvs
# error creating tnvd
Node('varioxB_vb.psi.ch',
'varioxB over SEA',
interface='tcp://10767',
)
Mod('seaconn',
'frappy_psi.sea.SeaClient',
'a SEA connection',
)
Mod('tvs',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tvs.varioxB.config',
remote_paths='.',
)
Mod('tvd',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tvd.varioxB.config',
remote_paths='.',
)
Mod('pstat',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='pstat.varioxB.config',
remote_paths='.',
)
Mod('pdyn',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='pdyn.varioxB.config',
remote_paths='.',
)
Mod('tneck1',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tneck1.varioxB.config',
remote_paths='.',
)
Mod('tneck2',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tneck2.varioxB.config',
remote_paths='.',
)
Mod('tnvs',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tnvs.varioxB.config',
remote_paths='.',
)
Mod('tnvd',
'frappy_psi.sea.SeaReadable',
io='seaconn',
json_descr='tnvd.varioxB.config',
remote_paths='.',
)

View File

@ -32,12 +32,13 @@ from frappy.modules import Drivable, Module, Parameter, Readable, Writable, Comm
class SimBase: class SimBase:
def __new__(cls, devname, logger, cfgdict, dispatcher): def __new__(cls, devname, logger, cfgdict, dispatcher):
extra_params = cfgdict.pop('extra_params', '') or cfgdict.pop('.extra_params', '') extra_params = cfgdict.pop('extra_params', '')['value']
if isinstance(extra_params, str):
extra_params = [v.strip() for v in extra_params.split(',')]
attrs = {} attrs = {}
if extra_params: if extra_params:
for k in extra_params['value'].split(','): for k in extra_params:
k = k.strip() attrs[k] = Parameter(f'extra_param: {k}',
attrs[k] = Parameter(f'extra_param: {k.strip()}',
datatype=FloatRange(), datatype=FloatRange(),
default=0.0) default=0.0)

View File

@ -109,7 +109,7 @@ class ChannelSwitcher(Drivable):
def read_status(self): def read_status(self):
now = time.monotonic() now = time.monotonic()
if self.status[0] == 'BUSY': if self.isBusy():
chan = self.channels[self.target] chan = self.channels[self.target]
if chan.is_switching(now, self._start_switch, self.switch_delay): if chan.is_switching(now, self._start_switch, self.switch_delay):
return self.status return self.status
@ -149,7 +149,7 @@ class ChannelSwitcher(Drivable):
def write_target(self, channel): def write_target(self, channel):
if channel not in self.channels: if channel not in self.channels:
raise ValueError(f'{channel!r} is no valid channel') raise ValueError(f'{channel!r} is no valid channel')
if channel == self.target and self.channels[channel].enabled: if channel == self.value and self.channels[channel].enabled:
return channel return channel
chan = self.channels[channel] chan = self.channels[channel]
chan.enabled = True chan.enabled = True

View File

@ -28,12 +28,12 @@ changed from the client is fixed for at least 10 seconds.
""" """
import re import re
import time import time
from math import copysign
from frappy.core import HasIO, StringIO, Readable, Drivable, Parameter, Command, \ 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.errors import ConfigError, BadValueError, HardwareError
from frappy.datatypes import FloatRange, StringType, EnumType, StructOf from frappy.datatypes import FloatRange, StringType, EnumType, StructOf
from frappy.states import HasStates, status_code, Retry from frappy.states import HasStates, status_code, Retry
from frappy.features import HasTargetLimits
import frappy_psi.magfield as magfield import frappy_psi.magfield as magfield
# floating point value followed with unit # floating point value followed with unit
@ -128,7 +128,7 @@ class Main(HasIO, Module):
class Channel: class Channel:
main = Attached(Main, default='main') main = Attached(Main)
channel = Property('channel name', StringType()) channel = Property('channel name', StringType())
pollinterval = Parameter(export=False) pollinterval = Parameter(export=False)
block_until = None block_until = None
@ -199,7 +199,7 @@ PersistencyMode = Enum(
) )
class BaseMagfield(HasStates, HasTargetLimits, Channel): class BaseMagfield(HasStates, Channel):
_status_text = '' _status_text = ''
_ready_text = '' _ready_text = ''
_error_text = '' _error_text = ''
@ -214,13 +214,13 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel):
dt = self.parameters['target'].datatype dt = self.parameters['target'].datatype
if dt.min < 1e-99: # make limits symmetric if dt.min < 1e-99: # make limits symmetric
dt.min = - dt.max dt.min = - dt.max
min_, max_ = self.target_limits # min_, max_ = self.target_limits
self.target_limits = [max(min_, dt.min), min(max_, dt.max)] # self.target_limits = [max(min_, dt.min), min(max_, dt.max)]
dt = self.parameters['ramp'].datatype dt = self.parameters['ramp'].datatype
if self.ramp == 0: # unconfigured: take max. if self.ramp == 0: # unconfigured: take max.
self.ramp = dt.max self.ramp = dt.max
if not isinstance(self, magfield.Magfield): 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.switch_heater = None
self.current = None self.current = None
@ -263,7 +263,7 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel):
setpoint=('<CH>_Setpoint', self.to_gauss), setpoint=('<CH>_Setpoint', self.to_gauss),
switch_heater=('<CH>_Heater', self.cvt_switch_heater), switch_heater=('<CH>_Heater', self.cvt_switch_heater),
cs_mode=('<CH>_Persistent Mode', self.cvt_cs_mode), cs_mode=('<CH>_Persistent Mode', self.cvt_cs_mode),
approach_mode=('<CH>_Approach', self.cvt_approach_mode), # no readback: approach_mode=('<CH>_Approach', self.cvt_approach_mode),
) )
def cvt_error(self, text): def cvt_error(self, text):
@ -297,13 +297,14 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel):
def write_target(self, target): def write_target(self, target):
self.reset_error() self.reset_error()
super().write_target(target) super().write_target(target)
return Done return target
def start_sweep(self, target): def start_sweep(self, target):
if self.approach_mode == self.approach_mode.OVERSHOOT: if self.approach_mode == self.approach_mode.OVERSHOOT:
o = self.overshoot['o'] sign = copysign(1, target - self.value) * copysign(1, target)
if (target - self.value) * o < 0: oval = copysign(self.overshoot['o'], sign)
self.write_overshoot(dict(self.overshoot, o=-o)) tval = self.overshoot['t']
self.sendcmd('Set:<CH>:SetOvershoot %g,%g' % (oval, tval))
self.write_ramp(self.ramp) self.write_ramp(self.ramp)
if self.hw_units == 'A': if self.hw_units == 'A':
self.sendcmd('Set:<CH>:Sweep %gA' % (target / self.A_to_G)) self.sendcmd('Set:<CH>:Sweep %gA' % (target / self.A_to_G))
@ -331,6 +332,8 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel):
# wait for overshoot/degauss/cycle # wait for overshoot/degauss/cycle
sm.stabilize_start = sm.now sm.stabilize_start = sm.now
return Retry return Retry
if sm.stabilize_start is None:
sm.stabilize_start = sm.now
if sm.now - sm.stabilize_start < self.wait_stable_field: if sm.now - sm.stabilize_start < self.wait_stable_field:
return Retry return Retry
return self.end_stablilize return self.end_stablilize
@ -368,18 +371,19 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel):
self.block('approach_mode') self.block('approach_mode')
return value return value
@classmethod # no readback:
def cvt_approach_mode(cls, text): # @classmethod
return cls.ApproachMode(text.upper()) # def cvt_approach_mode(cls, text):
# return cls.ApproachMode(text.upper())
overshoot = Parameter('overshoot [%] and hold time [s]', 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), readonly=False, default=dict(o=0, t=0),
group='approach_settings') group='approach_settings')
def write_overshoot(self, value): #def write_overshoot(self, value):
self.sendcmd('Set:<CH>:SetOvershoot %g,%g' % (value['o'], value['t'])) # self.sendcmd('Set:<CH>:SetOvershoot %g,%g' % (value['o'], value['t']))
return value # return value
cycle = Parameter('start value, damping factor, final value, hold time', cycle = Parameter('start value, damping factor, final value, hold time',
StructOf(s=FloatRange(-100, 100, unit='%'), StructOf(s=FloatRange(-100, 100, unit='%'),
@ -458,26 +462,36 @@ class MainField(BaseMagfield, magfield.Magfield):
def write_mode(self, mode): def write_mode(self, mode):
self.reset_error() self.reset_error()
super().write_mode(mode) # updates mode super().write_mode(mode) # updates mode
return Done return mode
@status_code('PREPARING') @status_code('PREPARING')
def start_ramp_to_field(self, sm): def start_ramp_to_field(self, sm):
self.sendcmd('Set:<CH>:SetApproach 0') # direct mode
self.start_sweep(self.value) self.start_sweep(self.value)
return self.ramp_to_field # -> stabilize_current -> start_switch_on return self.ramp_to_field # -> stabilize_current -> start_switch_on
@status_code('PREPARING') @status_code('PREPARING')
def start_switch_on(self, sm): def start_switch_on(self, sm):
self.write_cs_mode(CsMode.DRIVEN) self.write_cs_mode(CsMode.DRIVEN)
self.sendcmd('Set:<CH>:SetApproach 0') # direct mode
# self.block('switch_heater', 1, 60) # self.block('switch_heater', 1, 60)
self.start_sweep(self.value) self.start_sweep(self.value)
self.block('_ready_text', 'FALSE') 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 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') @status_code('PREPARING')
def wait_for_switch_on(self, sm): 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': if self._ready_text == 'FALSE':
return Retry return Retry
self.last_target(sm.target) self._last_target = sm.target
self.sendcmd('Set:<CH>:SetApproach %d' % self.approach_mode)
return self.start_ramp_to_target return self.start_ramp_to_target
def end_stablilize(self, sm): def end_stablilize(self, sm):
@ -491,16 +505,24 @@ class MainField(BaseMagfield, magfield.Magfield):
self.write_cs_mode(CsMode.SEMIPERSISTENT) self.write_cs_mode(CsMode.SEMIPERSISTENT)
else: # PERSISTENT or DISABLED else: # PERSISTENT or DISABLED
self.write_cs_mode(CsMode.PERSISTENT) self.write_cs_mode(CsMode.PERSISTENT)
self.sendcmd('Set:<CH>:SetApproach 0') # direct mode
self.start_sweep(sm.target) self.start_sweep(sm.target)
self.block('_ready_text', 'FALSE') self.block('_ready_text', 'FALSE')
self.block('switch_heater', 1) self.block('switch_heater', 1)
self.switch_off_time = sm.now
return self.wait_for_switch_off # -> start_ramp_to_zero return self.wait_for_switch_off # -> start_ramp_to_zero
wait_switch_off = Parameter('minimum time to wait for closing switch')
@status_code('PREPARING') @status_code('PREPARING')
def wait_for_switch_off(self, sm): 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: if self.switch_heater:
return Retry return Retry
self.last_target(sm.target) self._last_target = sm.target
if self.mode == PersistencyMode.SEMIPERSISTENT: if self.mode == PersistencyMode.SEMIPERSISTENT:
return self.final_status(IDLE, 'semipersistent') return self.final_status(IDLE, 'semipersistent')
return self.ramp_to_zero return self.ramp_to_zero

View File

@ -32,8 +32,8 @@ import time
import frappy.io import frappy.io
from frappy.datatypes import BoolType, EnumType, FloatRange, IntRange from frappy.datatypes import BoolType, EnumType, FloatRange, IntRange
from frappy.lib import formatStatusBits from frappy.lib import formatStatusBits
from frappy.core import Done, Drivable, Parameter, Property, CommonReadHandler, CommonWriteHandler from frappy.core import Command, Drivable, Parameter, Property, CommonReadHandler, CommonWriteHandler
from frappy.io import HasIO from frappy_psi.convergence import HasConvergence
from frappy_psi.channelswitcher import Channel, ChannelSwitcher from frappy_psi.channelswitcher import Channel, ChannelSwitcher
Status = Drivable.Status Status = Drivable.Status
@ -54,7 +54,7 @@ def parse1(string):
def parse(reply): def parse(reply):
return [parse1(s) for s in reply.split(',')] return tuple(parse1(s) for s in reply.split(','))
class StringIO(frappy.io.StringIO): class StringIO(frappy.io.StringIO):
@ -62,7 +62,7 @@ class StringIO(frappy.io.StringIO):
wait_before = 0.05 wait_before = 0.05
class Switcher(HasIO, ChannelSwitcher): class Switcher(frappy.io.HasIO, ChannelSwitcher):
value = Parameter(datatype=IntRange(1, 16)) value = Parameter(datatype=IntRange(1, 16))
target = Parameter(datatype=IntRange(1, 16)) target = Parameter(datatype=IntRange(1, 16))
use_common_delays = Parameter('use switch_delay and measure_delay instead of the channels pause and dwell', use_common_delays = Parameter('use switch_delay and measure_delay instead of the channels pause and dwell',
@ -73,14 +73,25 @@ class Switcher(HasIO, ChannelSwitcher):
_measure_delay = None _measure_delay = None
_switch_delay = None _switch_delay = None
def startModule(self, start_events): def initialReads(self):
super().startModule(start_events)
# disable unused channels # disable unused channels
display = []
for ch in range(1, 16): for ch in range(1, 16):
if ch not in self._channels: chan = self.channels.get(ch)
if chan:
if hasattr(chan, 'raw'):
display.append((ch, 2))
display.append((ch, 1))
else:
self.communicate('INSET %d,0,0,0,0,0;INSET?%d' % (ch, ch)) self.communicate('INSET %d,0,0,0,0,0;INSET?%d' % (ch, ch))
if len(display) > 4:
self.communicate('DISPLAY 2,2,1;*OPC?')
else:
self.communicate('DISPLAY 2,1,1;*OPC?')
for i, (ch, unit) in enumerate(display):
self.communicate(f'DISPFLD {i+1},{ch},{unit};*OPC?')
channelno, autoscan = parse(self.communicate('SCAN?')) channelno, autoscan = parse(self.communicate('SCAN?'))
if channelno in self._channels and self._channels[channelno].enabled: if channelno in self.channels and self.channels[channelno].enabled:
if not autoscan: if not autoscan:
return # nothing to do return # nothing to do
else: else:
@ -88,7 +99,7 @@ class Switcher(HasIO, ChannelSwitcher):
if channelno is None: if channelno is None:
self.status = 'ERROR', 'no enabled channel' self.status = 'ERROR', 'no enabled channel'
return return
self.communicate('SCAN %d,0;SCAN?' % channelno) self.set_active_channel(self.channels[channelno])
def doPoll(self): def doPoll(self):
"""poll buttons """poll buttons
@ -96,7 +107,7 @@ class Switcher(HasIO, ChannelSwitcher):
and check autorange during filter time and check autorange during filter time
""" """
super().doPoll() super().doPoll()
self._channels[self.target]._read_value() # check range or read self.channels[self.target]._read_value() # check range or read
channelno, autoscan = parse(self.communicate('SCAN?')) channelno, autoscan = parse(self.communicate('SCAN?'))
if autoscan: if autoscan:
# pressed autoscan button: switch off HW autoscan and toggle soft autoscan # pressed autoscan button: switch off HW autoscan and toggle soft autoscan
@ -104,17 +115,18 @@ class Switcher(HasIO, ChannelSwitcher):
self.communicate('SCAN %d,0;SCAN?' % self.value) self.communicate('SCAN %d,0;SCAN?' % self.value)
if channelno != self.value: if channelno != self.value:
# channel changed by keyboard, do not yet return new channel # channel changed by keyboard, do not yet return new channel
self.log.info('channel changed by keyboard %d!', channelno)
self.write_target(channelno) self.write_target(channelno)
chan = self._channels.get(channelno) chan = self.channels.get(channelno)
if chan is None: if chan is None:
self.log.info('invalid channel %d!', channelno)
channelno = self.next_channel(channelno) channelno = self.next_channel(channelno)
if channelno is None: if channelno is None:
raise ValueError('no channels enabled') raise ValueError('no channels enabled')
self.write_target(channelno) self.write_target(channelno)
chan = self._channels.get(self.value) chan = self.channels.get(self.value)
chan.read_autorange() chan.read_autorange()
chan.fix_autorange() # check for toggled autorange button chan.fix_autorange() # check for toggled autorange button
return Done
def write_switch_delay(self, value): def write_switch_delay(self, value):
self._switch_delay = value self._switch_delay = value
@ -149,7 +161,8 @@ class Switcher(HasIO, ChannelSwitcher):
self.measure_delay = chan.dwell self.measure_delay = chan.dwell
def set_active_channel(self, chan): def set_active_channel(self, chan):
self.communicate('SCAN %d,0;SCAN?' % chan.channel) channelno = parse(self.communicate('SCAN %d,0;SCAN?' % chan.channel))[0]
self.value = channelno
chan._last_range_change = time.monotonic() chan._last_range_change = time.monotonic()
self.set_delays(chan) self.set_delays(chan)
@ -167,7 +180,7 @@ class ResChannel(Channel):
enumerate(mag % val for mag in ['%guV', '%gmV'] enumerate(mag % val for mag in ['%guV', '%gmV']
for val in [2, 6.32, 20, 63.2, 200, 632]))} for val in [2, 6.32, 20, 63.2, 200, 632]))}
RES_SCALE = [2 * 10 ** (0.5 * i) for i in range(-7, 16)] # RES_SCALE[0] is not used RES_SCALE = [2 * 10 ** (0.5 * i) for i in range(-7, 16)] # RES_SCALE[0] is not used
MAX_RNG = len(RES_SCALE) - 1 MAX_RNG = len(RES_SCALE) - 2 # was - 1
channel = Property('the Lakeshore channel', datatype=IntRange(1, 16), export=False) channel = Property('the Lakeshore channel', datatype=IntRange(1, 16), export=False)
@ -189,19 +202,29 @@ class ResChannel(Channel):
_toggle_autorange = 'init' _toggle_autorange = 'init'
_prev_rdgrng = (1, 1) # last read values for icur and exc _prev_rdgrng = (1, 1) # last read values for icur and exc
_last_range_change = 0 _last_range_change = 0
_value = None # if not None, a fresh value
rdgrng_params = 'range', 'iexc', 'vexc' rdgrng_params = 'range', 'iexc', 'vexc'
inset_params = 'enabled', 'pause', 'dwell' inset_params = 'enabled', 'pause', 'dwell'
STATUS_MASK = 0x3f # mask T_OVER and T_UNDER
def communicate(self, command): def communicate(self, command):
# TODO: remove this and change to query
return self.switcher.communicate(command) return self.switcher.communicate(command)
def query(self, command):
return parse(self.switcher.communicate(command))
def change(self, command, *args):
cmd, _, qarg = command.partition(' ')
args = ','.join([qarg] + [f'{a:g}' for a in args])
return parse(self.switcher.communicate(f'{command}?{qarg};{command} {args}'))
def read_status(self): def read_status(self):
if not self.enabled: if not self.enabled:
return [self.Status.DISABLED, 'disabled'] return [self.Status.DISABLED, 'disabled']
if not self.channel == self.switcher.value == self.switcher.target: if self.switcher.isBusy():
return Done return self.status
result = int(self.communicate('RDGST?%d' % self.channel)) result = int(self.communicate('RDGST?%d' % self.channel)) & self.STATUS_MASK
result &= 0x37 # mask T_OVER and T_UNDER (change this when implementing temperatures instead of resistivities)
statustext = ' '.join(formatStatusBits(result, STATUS_BIT_LABELS)) statustext = ' '.join(formatStatusBits(result, STATUS_BIT_LABELS))
if statustext: if statustext:
return [self.Status.ERROR, statustext] return [self.Status.ERROR, statustext]
@ -212,13 +235,14 @@ class ResChannel(Channel):
now = time.monotonic() now = time.monotonic()
if now + 0.5 < max(self._last_range_change, self.switcher._start_switch) + self.pause: if now + 0.5 < max(self._last_range_change, self.switcher._start_switch) + self.pause:
return None return None
result = self.communicate('RDGR?%d' % self.channel) result = float(self.communicate('RDGR?%d' % self.channel))
result = float(result) if result == 0:
return None
if self.autorange: if self.autorange:
self.fix_autorange() self.fix_autorange()
if now + 0.5 > self._last_range_change + self.pause: if now + 0.5 > self._last_range_change + self.pause:
rng = int(max(self.minrange, self.range)) # convert from enum to int rng = int(max(self.minrange, self.range)) # convert from enum to int
if self.status[1] == '': if self.status[0] < self.Status.ERROR:
if abs(result) > self.RES_SCALE[rng]: if abs(result) > self.RES_SCALE[rng]:
if rng < 22: if rng < 22:
rng += 1 rng += 1
@ -236,15 +260,19 @@ class ResChannel(Channel):
return result return result
def read_value(self): def read_value(self):
if self.channel == self.switcher.value == self.switcher.target: if self.switcher.isBusy():
return self._read_value() return self.value if self.enabled else 0
return Done # return previous value value = self._read_value() if self._value is None else self._value
self._value = None
return self.value if value is None else value
def is_switching(self, now, last_switch, switch_delay): def is_switching(self, now, last_switch, switch_delay):
last_switch = max(last_switch, self._last_range_change) result = super().is_switching(now, last_switch, switch_delay)
if now + 0.5 > last_switch + self.pause: if not result: # the time since last switch has passed
self._read_value() # adjust range only self._value = self._read_value() # for autorange
return super().is_switching(now, last_switch, switch_delay) # now check for the time since last range change
result = super().is_switching(now, self._last_range_change, switch_delay)
return result
@CommonReadHandler(rdgrng_params) @CommonReadHandler(rdgrng_params)
def read_rdgrng(self): def read_rdgrng(self):
@ -327,3 +355,88 @@ class ResChannel(Channel):
if not on: if not on:
settle = 0 settle = 0
return settle return settle
class TemperatureChannel(ResChannel):
raw = Parameter('raw reistance value', FloatRange(unit='Ohm'))
value = Parameter('temperature sensor', FloatRange(0, unit='K'))
STATUS_MASK = 0xff # accept T_OVER and T_UNDER
def read_raw(self):
if self.channel == self.switcher.value == self.switcher.target:
return self._read_value() or self.raw
return self.raw or 0
def read_value(self):
if self.channel == self.switcher.value == self.switcher.target:
return float(self.communicate('RDGK?%d' % self.channel))
return self.value if self.enabled else 0
class TemperatureLoop(HasConvergence, TemperatureChannel, Drivable):
loop = Property('lakshore loop', IntRange(0, 1), default=0) # TODO: implemented specific issues of loop 1
target = Parameter('setpoint', FloatRange(0, unit='$'))
control_active = Parameter('we are controlling', BoolType(), default=0)
minheater = Parameter('minimal heater current', FloatRange(0, 0.01, unit='A'), readonly=False, default=0)
HTRRNG = {n: i for i, n in enumerate(['off', '30uA', '100uA', '300uA', '1mA', '3mA', '10mA', '30mA', '100mA'])}
htrrng = Parameter('', EnumType(HTRRNG), readonly=False)
_control_active = False
@Command
def control_off(self):
"""switch control off"""
self._control_active = False
self.communicate(f'RANGE {self.loop},0;RANGE?{self.loop}')
self.read_control_active()
def min_percent(self):
curr = 10 ** (int(self.htrrng) * 0.5 - 5.0)
result = 100 * min(1.0, self.minheater / curr)
return round(result, 2)
def set_htrrng(self):
if self._control_active:
newhtr = int(self.htrrng) if self._control_active else 0
htrrng = int(self.communicate(f'RANGE?{self.loop}'))
if htrrng != newhtr:
if newhtr:
self.log.info('switched heater on %d', newhtr)
self.communicate(f'RANGE {self.loop},{newhtr};RANGE?{self.loop}')
def read_control_active(self):
self.set_htrrng()
return self._control_active
def read_target(self):
if self._control_active:
return float(self.communicate(f'SETP?{self.loop}'))
return 0
def write_htrrng(self, value):
if self._control_active:
self.communicate('RANGE {self.loop},{int(value)};*OPC?')
return value
def write_target(self, target):
outmode = (5, self.channel, 0, 0, 1, 3)
prev = parse(self.communicate(f'OUTMODE?{self.loop}'))
if outmode != prev:
self.communicate(f'OUTMODE {self.loop},%g,%g,%g,%g,%g,%g;*OPC?' % tuple(outmode))
self.communicate(f'MOUT {self.loop},{self.min_percent()};*OPC?')
for chan in self.switcher.channels.values():
chan._control_active = False
self._control_active = True
self.read_control_active()
self.convergence_start()
# do not return the readback value, as it might not yet be correct
self.communicate(f'SETP {self.loop},{target};*OPC?')
return target
#def write_ctrlpars(self, ctrlpars):
# p, i, d = self.change(f'PID {self.loop}', ctrlpars['p'], ctrlpars['i'], ctrlpars['d'])
# return {'p': p, 'i': i, 'd': d}
#def read_ctrlpars(self):
# p, i, d = self.query(f'PID? {self.loop}')
# return {'p': p, 'i': i, 'd': d}

View File

@ -22,11 +22,12 @@
"""modules to access parameters""" """modules to access parameters"""
from frappy.core import Drivable, IDLE, Attached, StringType, Property, \ from frappy.core import Drivable, EnumType, IDLE, Attached, StringType, Property, \
Parameter, FloatRange, Readable Parameter, FloatRange, Readable, ERROR
from frappy.errors import ConfigError from frappy.errors import ConfigError
from frappy_psi.convergence import HasConvergence from frappy_psi.convergence import HasConvergence
from frappy_psi.mixins import HasRamp from frappy_psi.mixins import HasRamp
from frappy.lib import merge_status
class Par(Readable): class Par(Readable):
@ -121,3 +122,111 @@ class Converging(HasConvergence, Driv):
class RampDriv(HasRamp, Driv): class RampDriv(HasRamp, Driv):
pass pass
def set_enabled(modobj, value):
"""set enabled on module if available"""
if hasattr(modobj, 'enabled') and modobj.enabled != value:
modobj.write_enabled(value)
def get_value(obj, default):
"""get the value of given module. if not valid, return the limit (min_high or max_low)"""
if not getattr(obj, 'enabled', True):
return default
# consider also that a value 0 is invalid
return (obj.value if IDLE <= obj.status[0] < ERROR else 0) or default
LOW = 0
HIGH = 1
class SwitchDriv(HasConvergence, Drivable):
low = Attached(description='low range module')
high = Attached(description='high range module')
min_high = Parameter('minimum high target', FloatRange(unit='$'), readonly=False)
max_low = Parameter('maximum low target', FloatRange(unit='$'), readonly=False)
# disable_other = Parameter('whether to disable unused channel', BoolType(), readonly=False)
selected = Parameter('selected module', EnumType(low=LOW, high=HIGH), readonly=False, default=0)
_switch_target = None # if not None, switch to selection mhen mid range is reached
# TODO: copy units from attached module
# TODO: callbacks for updates
def doPoll(self):
super().doPoll()
if self.isBusy():
if self._switch_target is not None:
mid = (self.min_high + self.max_low) * 0.5
if self._switch_target == HIGH:
low = get_value(self.low, mid) # returns mid when low is invalid
if low > mid:
self.value = self.low.value
self._switch_target = None
self.write_target(self.target)
return
else:
high = get_value(self.high, mid) # return mid then high is invalid
if high < mid:
self.value = self.high.value
self._switch_target = None
self.write_target(self.target)
return
else:
low = get_value(self.low, self.max_low)
high = get_value(self.high, self.min_high)
low_valid = low < self.max_low
high_valid = high > self.min_high
if high_valid and high > self.max_low:
if not low_valid:
set_enabled(self.low, False)
return
if low_valid and low < self.min_high:
if not high_valid:
set_enabled(self.high, False)
return
set_enabled(self.low, True)
set_enabled(self.high, True)
def read_value(self):
return self.low.value if self.selected == LOW else self.high.value
def read_status(self):
status = self.low.status if self.selected == LOW else self.high.status
if status[0] >= ERROR:
return status
return super().read_status() # convergence status
def write_target(self, target):
this, other = self.low, self.high
selected = self.selected
target1 = target
self._switch_target = None
if target > self.max_low:
if self.value < self.min_high:
target1 = self.max_low
self._switch_target = HIGH
selected = LOW
else:
this, other = other, this
selected = HIGH
elif target < self.min_high:
if self.value > self.max_low:
target1 = self.min_high
self._switch_target = LOW
this, other = other, this
selected = HIGH
else:
selected = LOW
elif self.selected == HIGH:
this, other = other, this
if hasattr(other, 'control_off'):
other.control_off()
set_enabled(this, True)
set_enabled(other, False)
self.write_selected(selected)
self.convergence_start()
self.log.info('target=%g (%s)', target, this.name)
this.write_target(target1)
return target

View File

@ -32,6 +32,7 @@ from frappy.core import Done, Command, EnumType, FloatRange, IntRange, \
from frappy.errors import CommunicationFailedError, HardwareError from frappy.errors import CommunicationFailedError, HardwareError
from frappy.features import HasOffset from frappy.features import HasOffset
from frappy.states import HasStates, status_code, Retry from frappy.states import HasStates, status_code, Retry
from frappy.lib import formatStatusBits
class PhytronIO(StringIO): class PhytronIO(StringIO):
@ -88,15 +89,8 @@ class Motor(HasOffset, HasStates, PersistentMixin, HasIO, Drivable):
_prev_diff = 0 # for checking progress _prev_diff = 0 # for checking progress
_intermediate_target = 0 _intermediate_target = 0
_stopped_at = 0 _stopped_at = 0
status_bits = ['power stage error', 'undervoltage', 'overtemperature', 'active',
STATUS_MAP = { 'lower switch active', 'upper switch active', 'step failure', 'encoder error']
'08': (IDLE, ''),
'01': (ERROR, 'power stage failure'),
'02': (ERROR, 'power too low'),
'04': (ERROR, 'power stage over temperature'),
'07': (ERROR, 'no power stage'),
'80': (ERROR, 'encoder failure'),
}
def get(self, cmd): def get(self, cmd):
return self.communicate(f'{self.address:x}{self.axis}{cmd}') return self.communicate(f'{self.address:x}{self.axis}{cmd}')
@ -196,14 +190,19 @@ class Motor(HasOffset, HasStates, PersistentMixin, HasIO, Drivable):
sysstatus = self.communicate(f'{self.address:x}SE') sysstatus = self.communicate(f'{self.address:x}SE')
try: try:
sysstatus = sysstatus[1:4] if self.axis == 'X' else sysstatus[5:8] sysstatus = sysstatus[1:4] if self.axis == 'X' else sysstatus[5:8]
status = self.STATUS_MAP[sysstatus[1:]] hexstatus = int(sysstatus, base=16)
except Exception: # can not interprete the reply, probably communication error status_items = formatStatusBits(hexstatus & 0xf7, self.status_bits)
if status_items:
status = ERROR, ', '.join(status_items)
else:
status = IDLE, ''
except TimeoutError: # Exception: # can not interprete the reply, probably communication error
self.log.warning('bad status reply %r', sysstatus) self.log.warning('bad status reply %r', sysstatus)
continue continue
break break
else: else:
status = (ERROR, f'unknown status after 3 tries {sysstatus!r}') status = (ERROR, f'unknown status after 3 tries {sysstatus!r}')
self._running = sysstatus[0] != '1' self._running = (hexstatus & 0x100) == 0
if status[0] == ERROR: if status[0] == ERROR:
self._blocking_error = status[1] self._blocking_error = status[1]
return status return status

View File

@ -108,7 +108,6 @@ class SeaClient(ProxyClient, Module):
visibility = 'expert' visibility = 'expert'
default_json_file = {} default_json_file = {}
_connect_thread = None _connect_thread = None
_service_manager = None
_instance = None _instance = None
_last_connect = 0 _last_connect = 0
@ -162,15 +161,11 @@ class SeaClient(ProxyClient, Module):
self.syncio = None self.syncio = None
self._last_connect = time.time() self._last_connect = time.time()
if self._instance: if self._instance:
if not self._service_manager:
if self._service_manager is None:
try: try:
from servicemanager import SeaManager # pylint: disable=import-outside-toplevel from servicemanager import SeaManager # pylint: disable=import-outside-toplevel
self._service_manager = SeaManager() SeaManager().do_start(self._instance)
except ImportError: except ImportError:
self._service_manager = False pass
if self._service_manager:
self._service_manager.do_start(self._instance)
if '//' not in self.uri: if '//' not in self.uri:
self.uri = 'tcp://' + self.uri self.uri = 'tcp://' + self.uri
self.asynio = AsynConn(self.uri) self.asynio = AsynConn(self.uri)
@ -185,7 +180,7 @@ class SeaClient(ProxyClient, Module):
else: else:
raise CommunicationFailedError('reply %r should be "Login OK"' % reply) raise CommunicationFailedError('reply %r should be "Login OK"' % reply)
result = self.request('frappy_config %s %s' % (self.service, self.config)) result = self.request('frappy_config %s %s' % (self.service, self.config))
if result not in {'0', '1'}: if result.startswith('ERROR:'):
raise CommunicationFailedError(f'reply from frappy_config: {result}') raise CommunicationFailedError(f'reply from frappy_config: {result}')
# frappy_async_client switches to the json protocol (better for updates) # frappy_async_client switches to the json protocol (better for updates)
self.asynio.writeline(b'frappy_async_client') self.asynio.writeline(b'frappy_async_client')

View File

@ -38,7 +38,7 @@ class DPM3(Readable):
_pos = 0 _pos = 0
def read_value(self): def read_value(self):
mot = self._motor mot = self.motor
d = self.friction * self.slope d = self.friction * self.slope
self._pos = clamp(self._pos, mot.value - d, mot.value + d) self._pos = clamp(self._pos, mot.value - d, mot.value + d)
f = (mot.value - self._pos) / self.slope f = (mot.value - self._pos) / self.slope

View File

@ -36,8 +36,9 @@ actions_map.mapping['NONE'] = actions.none # when writing, STOP is used instead
class Action(MercuryChannel, Writable): class Action(MercuryChannel, Writable):
kind = 'ACTN' kind = 'ACTN'
cooldown_channel = Property('cool down channel', StringType(), 'T5') cooldown_channel = Property('cool down channel', StringType(), 'T3')
mix_channel = Property('mix channel', StringType(), 'T5') mix_channel = Property('mix channel', StringType(), 'T5')
still_channel = Property('cool down channel', StringType(), 'T4')
value = Parameter('running action', EnumType(actions)) value = Parameter('running action', EnumType(actions))
target = Parameter('action to do', EnumType(none=0, condense=1, collect=3), readonly=False) target = Parameter('action to do', EnumType(none=0, condense=1, collect=3), readonly=False)
_target = 0 _target = 0
@ -51,8 +52,9 @@ class Action(MercuryChannel, Writable):
def write_target(self, value): def write_target(self, value):
self._target = value self._target = value
self.change('SYS:DR:CHAN:COOL', self.cooldown_channel, str) self.change('SYS:DR:CHAN:COOL', self.cooldown_channel, str)
# self.change('SYS:DR:CHAN:MC', self.mix_channel, str) self.change('SYS:DR:CHAN:STIL', self.still_channel, str)
# self.change('DEV:T5:TEMP:MEAS:ENAB', 'ON', str) self.change('SYS:DR:CHAN:MC', self.mix_channel, str)
self.change('DEV:T5:TEMP:MEAS:ENAB', 'ON', str)
return self.change('SYS:DR:ACTN', value, actions_map) return self.change('SYS:DR:ACTN', value, actions_map)
# actions: # actions:

View File

@ -26,9 +26,9 @@ import math
from frappy.core import Drivable, Parameter, FloatRange, Done, \ from frappy.core import Drivable, Parameter, FloatRange, Done, \
Attached, Command, PersistentMixin, PersistentParam, BoolType Attached, Command, PersistentMixin, PersistentParam, BoolType
from frappy.errors import BadValueError, SECoPError from frappy.errors import BadValueError, SECoPError
from frappy.lib.statemachine import Retry, StateMachine, Restart from frappy.lib.statemachine import Retry, StateMachine, Stop
# TODO: fix with new state machine! # TODO: to be tested, or better migrated to new state machine!
class Error(SECoPError): class Error(SECoPError):
@ -46,11 +46,11 @@ class Uniax(PersistentMixin, Drivable):
pid_i = PersistentParam('integral', FloatRange(), readonly=False, default=0.5, persistent='auto') pid_i = PersistentParam('integral', FloatRange(), readonly=False, default=0.5, persistent='auto')
filter_interval = Parameter('filter time', FloatRange(0, 60, unit='s'), readonly=False, default=5) filter_interval = Parameter('filter time', FloatRange(0, 60, unit='s'), readonly=False, default=5)
current_step = Parameter('', FloatRange(unit='deg'), default=0) current_step = Parameter('', FloatRange(unit='deg'), default=0)
force_offset = PersistentParam('transducer offset', FloatRange(unit='N'), readonly=False, default=0, force_offset = PersistentParam('transducer offset', FloatRange(unit='N'), readonly=False, value=0,
initwrite=True, persistent='auto') persistent='auto')
hysteresis = PersistentParam('force hysteresis', FloatRange(0, 190, unit='N'), readonly=False, default=5, hysteresis = PersistentParam('force hysteresis', FloatRange(0, 190, unit='N'), readonly=False, default=5,
persistent='auto') persistent='auto')
adjusting = Parameter('', BoolType(), readonly=False, default=False, initwrite=True) adjusting = Parameter('', BoolType(), readonly=False, value=False)
adjusting_current = PersistentParam('current when adjusting force', FloatRange(0, 2.8, unit='A'), readonly=False, adjusting_current = PersistentParam('current when adjusting force', FloatRange(0, 2.8, unit='A'), readonly=False,
default=0.5, persistent='auto') default=0.5, persistent='auto')
safe_step = PersistentParam('max. motor step when adjusting force', FloatRange(0, unit='deg'), readonly=False, safe_step = PersistentParam('max. motor step when adjusting force', FloatRange(0, unit='deg'), readonly=False,
@ -116,11 +116,15 @@ class Uniax(PersistentMixin, Drivable):
def motor_busy(self): def motor_busy(self):
mot = self.motor mot = self.motor
if mot.isBusy(): if mot.isBusy():
if mot.target != self._mot_target: if self._mot_target is not None and mot.target != self._mot_target:
raise Error('control stopped - motor moved directly') raise Error('control stopped - motor moved directly')
return True return True
return False return False
def motor_stop(self):
self.motor.stop()
self._mot_target = None
def read_value(self): def read_value(self):
try: try:
self._force = force = self.transducer.read_value() self._force = force = self.transducer.read_value()
@ -142,7 +146,7 @@ class Uniax(PersistentMixin, Drivable):
force = self._sum / self._cnt force = self._sum / self._cnt
self.reset_filter(now) self.reset_filter(now)
if abs(force) > self.limit + self.hysteresis: if abs(force) > self.limit + self.hysteresis:
self.motor.stop() self.motor_stop()
self.status = 'ERROR', 'above max limit' self.status = 'ERROR', 'above max limit'
self.log.error(self.status[1]) self.log.error(self.status[1])
self.read_target() self.read_target()
@ -188,8 +192,8 @@ class Uniax(PersistentMixin, Drivable):
def cleanup(self, state): def cleanup(self, state):
"""in case of error, set error status""" """in case of error, set error status"""
if state.stopped: # stop or restart if state.next_task: # stop or restart
if state.stopped is Restart: if not isinstance(state.next_task, Stop):
return return
self.status = 'IDLE', 'stopped' self.status = 'IDLE', 'stopped'
self.log.warning('stopped') self.log.warning('stopped')
@ -200,7 +204,7 @@ class Uniax(PersistentMixin, Drivable):
else: else:
self.log.error('%r raised in state %r', str(state.last_error), state.status_string) self.log.error('%r raised in state %r', str(state.last_error), state.status_string)
self.read_target() # make target invalid self.read_target() # make target invalid
self.motor.stop() self.motor_stop()
self.write_adjusting(False) self.write_adjusting(False)
def reset_progress(self, state): def reset_progress(self, state):
@ -234,7 +238,7 @@ class Uniax(PersistentMixin, Drivable):
state.direction = math.copysign(1, self.target - self.value) state.direction = math.copysign(1, self.target - self.value)
state.pid_fact = 1 state.pid_fact = 1
if self.motor_busy(): if self.motor_busy():
return Retry() return Retry
self.value = self._force self.value = self._force
force_step = self.target - self.value force_step = self.target - self.value
if abs(force_step) < self.tolerance: if abs(force_step) < self.tolerance:
@ -255,6 +259,7 @@ class Uniax(PersistentMixin, Drivable):
self.status = 'BUSY', 'adjusting force' self.status = 'BUSY', 'adjusting force'
elif not self.check_progress(state): elif not self.check_progress(state):
if abs(self.value) < self.hysteresis: if abs(self.value) < self.hysteresis:
motor_dif = abs(self.motor.value - state.prev_pos)
if motor_dif > self.motor_play: if motor_dif > self.motor_play:
self.log.warning('adjusting failed - try to find zero pos') self.log.warning('adjusting failed - try to find zero pos')
self.set_zero_pos(self.target, None) self.set_zero_pos(self.target, None)
@ -265,15 +270,15 @@ class Uniax(PersistentMixin, Drivable):
self.log.warning('no substantial progress since %d sec', self.timeout) self.log.warning('no substantial progress since %d sec', self.timeout)
self.status = 'IDLE', 'adjusting timeout' self.status = 'IDLE', 'adjusting timeout'
self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * state.pid_fact) self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * state.pid_fact)
return Retry() return Retry
def within_tolerance(self, state): def within_tolerance(self, state):
"""within tolerance""" """within tolerance"""
if state.init: if state.init:
self.status = 'IDLE', 'within tolerance' self.status = 'IDLE', 'within tolerance'
return Retry() return Retry
if self.motor_busy(): if self.motor_busy():
return Retry() return Retry
force_step = self.target - self.value force_step = self.target - self.value
if abs(force_step) < self.tolerance * 0.5: if abs(force_step) < self.tolerance * 0.5:
self.current_step = 0 self.current_step = 0
@ -282,16 +287,16 @@ class Uniax(PersistentMixin, Drivable):
self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * 0.1) self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * 0.1)
if abs(force_step) > self.tolerance: if abs(force_step) > self.tolerance:
return self.out_of_tolerance return self.out_of_tolerance
return Retry() return Retry
def out_of_tolerance(self, state): def out_of_tolerance(self, state):
"""out of tolerance""" """out of tolerance"""
if state.init: if state.init:
self.status = 'WARN', 'out of tolerance' self.status = 'WARN', 'out of tolerance'
state.in_since = 0 state.in_since = 0
return Retry() return Retry
if self.motor_busy(): if self.motor_busy():
return Retry() return Retry
force_step = self.target - self._force force_step = self.target - self._force
if abs(force_step) < self.tolerance: if abs(force_step) < self.tolerance:
if state.in_since == 0: if state.in_since == 0:
@ -299,10 +304,10 @@ class Uniax(PersistentMixin, Drivable):
if state.now > state.in_since + 10: if state.now > state.in_since + 10:
return self.within_tolerance return self.within_tolerance
if abs(force_step) < self.tolerance * 0.5: if abs(force_step) < self.tolerance * 0.5:
return Retry() return Retry
self.check_progress(state) self.check_progress(state)
self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * 0.1) self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * 0.1)
return Retry() return Retry
def find(self, state): def find(self, state):
"""find active (engaged) range""" """find active (engaged) range"""
@ -315,7 +320,7 @@ class Uniax(PersistentMixin, Drivable):
if abs_force > self.hysteresis or abs_force > self.target * direction: if abs_force > self.hysteresis or abs_force > self.target * direction:
if self.motor_busy(): if self.motor_busy():
self.log.info('motor stopped - substantial force detected: %g', self.value) self.log.info('motor stopped - substantial force detected: %g', self.value)
self.motor.stop() self.motor_stop()
elif state.prev_direction == 0: elif state.prev_direction == 0:
return self.adjust return self.adjust
if abs_force > self.hysteresis: if abs_force > self.hysteresis:
@ -326,9 +331,9 @@ class Uniax(PersistentMixin, Drivable):
return self.free return self.free
if self.motor_busy(): if self.motor_busy():
if direction == -state.prev_direction: # target direction changed if direction == -state.prev_direction: # target direction changed
self.motor.stop() self.motor_stop()
state.init_find = True # restart find state.init_find = True # restart find
return Retry() return Retry
zero_pos = self.zero_pos(self.target) zero_pos = self.zero_pos(self.target)
if state.prev_direction: # find already started if state.prev_direction: # find already started
if abs(self.motor.target - self.motor.value) > self.motor.tolerance: if abs(self.motor.target - self.motor.value) > self.motor.tolerance:
@ -336,7 +341,7 @@ class Uniax(PersistentMixin, Drivable):
self.write_adjusting(True) self.write_adjusting(True)
self.log.info('one step to %g', self.motor.value + self.safe_step) self.log.info('one step to %g', self.motor.value + self.safe_step)
self.drive_relative(direction * self.safe_step) self.drive_relative(direction * self.safe_step)
return Retry() return Retry
else: else:
state.prev_direction = math.copysign(1, self.target) state.prev_direction = math.copysign(1, self.target)
side_name = 'negative' if direction == -1 else 'positive' side_name = 'negative' if direction == -1 else 'positive'
@ -347,14 +352,14 @@ class Uniax(PersistentMixin, Drivable):
self.write_adjusting(False) self.write_adjusting(False)
self.log.info('change side to %g', zero_pos) self.log.info('change side to %g', zero_pos)
self.drive_relative(zero_pos - self.motor.value) self.drive_relative(zero_pos - self.motor.value)
return Retry() return Retry
# we are already at or beyond zero_pos # we are already at or beyond zero_pos
return self.adjust return self.adjust
self.write_adjusting(False) self.write_adjusting(False)
self.status = 'BUSY', 'find %s side' % side_name self.status = 'BUSY', 'find %s side' % side_name
self.log.info('one turn to %g', self.motor.value + direction * 360) self.log.info('one turn to %g', self.motor.value + direction * 360)
self.drive_relative(direction * 360) self.drive_relative(direction * 360)
return Retry() return Retry
def free(self, state): def free(self, state):
"""free from high force at other end""" """free from high force at other end"""
@ -362,7 +367,7 @@ class Uniax(PersistentMixin, Drivable):
state.free_way = None state.free_way = None
self.reset_progress(state) self.reset_progress(state)
if self.motor_busy(): if self.motor_busy():
return Retry() return Retry
self.value = self._force self.value = self._force
if abs(self.value) > abs(state.force_before_free) + self.hysteresis: if abs(self.value) > abs(state.force_before_free) + self.hysteresis:
raise Error('force increase while freeing') raise Error('force increase while freeing')
@ -377,7 +382,7 @@ class Uniax(PersistentMixin, Drivable):
raise Error('freeing failed') raise Error('freeing failed')
state.free_way += self.safe_step state.free_way += self.safe_step
self.drive_relative(direction * self.safe_step) self.drive_relative(direction * self.safe_step)
return Retry() return Retry
def write_target(self, target): def write_target(self, target):
if abs(target) > self.limit: if abs(target) > self.limit:
@ -399,7 +404,7 @@ class Uniax(PersistentMixin, Drivable):
return Done return Done
def read_target(self): def read_target(self):
if self._state.state is None: if self._state.statefunc is None:
if self.status[1]: if self.status[1]:
raise Error(self.status[1]) raise Error(self.status[1])
raise Error('inactive') raise Error('inactive')
@ -409,7 +414,7 @@ class Uniax(PersistentMixin, Drivable):
def stop(self): def stop(self):
if self.motor.isBusy(): if self.motor.isBusy():
self.log.info('stop motor') self.log.info('stop motor')
self.motor.stop() self.motor_stop()
self.status = 'IDLE', 'stopped' self.status = 'IDLE', 'stopped'
self._state.stop() self._state.stop()