changes for leiden dil
- fixes on frappy_psiahcapbridge - fixes on cfg files - add cp1000 sea cfg files
This commit is contained in:
@@ -3,20 +3,16 @@ Node('ah2700.frappy.psi.ch',
|
||||
)
|
||||
|
||||
Mod('cap_io',
|
||||
'frappy_psi.ah2700.Ah2700IO',
|
||||
'',
|
||||
uri='linse-976d-ts:3006',
|
||||
'frappy_psi.ahcapbridge.IO', '',
|
||||
uri='linse-leiden-ts:3002'
|
||||
)
|
||||
|
||||
Mod('cap',
|
||||
'frappy_psi.ah2700.Capacitance',
|
||||
'frappy_psi.ahcapbridge.AH2700',
|
||||
'capacitance',
|
||||
io = 'cap_io',
|
||||
io='cap_io',
|
||||
loss_module = 'loss',
|
||||
freq_module = 'freq',
|
||||
)
|
||||
|
||||
Mod('loss',
|
||||
'frappy_psi.parmod.Par',
|
||||
'loss parameter',
|
||||
read='cap.loss',
|
||||
unit='deg',
|
||||
)
|
||||
|
||||
|
||||
31
cfg/addons/ahtwo_cfg.py
Normal file
31
cfg/addons/ahtwo_cfg.py
Normal file
@@ -0,0 +1,31 @@
|
||||
Node('ahtwo.frappy.psi.ch',
|
||||
'Andeen Hagerlin 2700 and 2550 Capacitance Bridges',
|
||||
)
|
||||
|
||||
# TODO: adapt names (cap, cap2) to your experiment
|
||||
|
||||
Mod('cap_io',
|
||||
'frappy_psi.ahcapbridge.IO', '',
|
||||
uri='linse-leiden-ts:3002'
|
||||
)
|
||||
|
||||
Mod('cap',
|
||||
'frappy_psi.ahcapbridge.AH2700',
|
||||
'capacitance',
|
||||
io='cap_io',
|
||||
loss_module = 'loss',
|
||||
freq_module = 'freq',
|
||||
)
|
||||
|
||||
Mod('cap2_io',
|
||||
'frappy_psi.ahcapbridge.IO', '',
|
||||
uri='linse-leiden-ts:3001'
|
||||
)
|
||||
|
||||
#Mod('cap2',
|
||||
# 'frappy_psi.ahcapbridge.AH2550',
|
||||
# 'capacitance',
|
||||
# io='cap2_io',
|
||||
# loss_module = 'loss2',
|
||||
#)
|
||||
|
||||
@@ -3,8 +3,15 @@ Node('AH2700Test.psi.ch',
|
||||
'tcp://5000',
|
||||
)
|
||||
|
||||
Mod('cap',
|
||||
'frappy_psi.ah2700.Capacitance',
|
||||
'capacitance',
|
||||
uri='ldmse3-ts:3015',
|
||||
Mod('io',
|
||||
'frappy_psi.ahcapbridge.IO', '',
|
||||
uri='linse-leiden-ts:3002'
|
||||
)
|
||||
|
||||
Mod('cap',
|
||||
'frappy_psi.ahcapbridge.AH2700',
|
||||
'capacitance',
|
||||
io='io',
|
||||
loss_module = 'loss',
|
||||
freq_module = 'freq',
|
||||
)
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
Node('leiden370.config.sea.psi.ch',
|
||||
'''30 K - Leidendil Pulsetube with ls370''',
|
||||
)
|
||||
Mod('sea_main',
|
||||
'frappy_psi.sea.SeaClient',
|
||||
'main sea connection for leiden370.config',
|
||||
config = 'leiden370.config',
|
||||
service = 'main',
|
||||
)
|
||||
|
||||
for name in ['T3K', 'Tstill', 'T50mK', 'Tmxlow', 'Tmxhigh', 'Tmxcx', 'Tblueo',
|
||||
'Tpt50', 'Tpt3high', 'Tpt3low', 'Twhite', 'Tgreen']:
|
||||
mname = name.replace('T','T_')
|
||||
Mod(mname,
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io='sea_main',
|
||||
sea_object='tt',
|
||||
rel_paths=[name],
|
||||
value=Param(unit='K'),
|
||||
extra_modules = ['raw'],
|
||||
)
|
||||
Mod(name.replace('T', 'R_'),
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io='sea_main',
|
||||
value=Param(unit='Ohm'),
|
||||
single_module=f'{mname}.raw'
|
||||
)
|
||||
|
||||
Mod('cmn',
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io = 'sea_main',
|
||||
sea_object = 'cmn',
|
||||
extra_modules = ['u1', 'u2', 'temp'],
|
||||
)
|
||||
|
||||
Mod('T_cmn',
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io='sea_main',
|
||||
value=Param(unit='K'),
|
||||
single_module='cmn.temp',
|
||||
)
|
||||
|
||||
Mod('V_fixp',
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io='sea_main',
|
||||
value=Param(unit='V'),
|
||||
single_module='cmn.u2',
|
||||
)
|
||||
|
||||
Mod('V_cmn',
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io='sea_main',
|
||||
value=Param(unit='V'),
|
||||
single_module='cmn.u1',
|
||||
)
|
||||
|
||||
Mod('tcs_io',
|
||||
'frappy_psi.tcs.IO',
|
||||
'tcs communication',
|
||||
uri='linse-leiden-ts:3005',
|
||||
)
|
||||
|
||||
Mod('still_htr',
|
||||
'frappy_psi.tcs.Heater',
|
||||
'still heater',
|
||||
io='tcs_io',
|
||||
channel=2,
|
||||
)
|
||||
|
||||
Mod('mix_htr',
|
||||
'frappy_psi.tcs.WrappedHeater',
|
||||
'mixing chamber heater',
|
||||
io='tcs_io',
|
||||
channel=3,
|
||||
)
|
||||
|
||||
Mod('drive_mix',
|
||||
'frappy_psi.picontrol.PIctrl',
|
||||
'controlled temperature ',
|
||||
input_module = 'T_mxlow',
|
||||
output_module = 'mix_htr',
|
||||
output_min = 0,
|
||||
output_max = 0.02,
|
||||
p = 5,
|
||||
itime = 60,
|
||||
)
|
||||
|
||||
Mod('drive_cmn',
|
||||
'frappy_psi.picontrol.PIctrl',
|
||||
'controlled temperature ',
|
||||
input_module = 'T_cmn',
|
||||
output_module = 'mix_htr',
|
||||
output_min = 0,
|
||||
output_max = 1e-3,
|
||||
p = 5,
|
||||
itime = 120,
|
||||
)
|
||||
|
||||
Mod('drive_fixp',
|
||||
'frappy_psi.picontrol.PI',
|
||||
'controlled temperature ',
|
||||
value=Param(unit='V'),
|
||||
input_module = 'V_fixp',
|
||||
output_module = 'drive_mix',
|
||||
output_min = 0.0,
|
||||
output_max = 0.01,
|
||||
p = 1,
|
||||
itime = 120,
|
||||
)
|
||||
|
||||
224
cfg/main/leiden_cfg.py
Normal file
224
cfg/main/leiden_cfg.py
Normal file
@@ -0,0 +1,224 @@
|
||||
Node('leiden.psi.ch',
|
||||
'''Leiden Dilution''',
|
||||
)
|
||||
|
||||
ah2700_uri = 'linse-leiden-ts:3002' # used in cfg/addons/ahtwo_cfg.pt
|
||||
ls370_uri = 'linse-leiden-ts:3004' # used in ~/sea/tcl/leiden.config
|
||||
tcs_uri = 'linse-leiden-ts:3005'
|
||||
#nanov_uri = 'linse-leiden-ts:3006' # used in ~/sea/tcl/leiden.config
|
||||
k2601b_uri = 'linse-leiden-ts:3006' # used for HC experiment as heater
|
||||
dilhtr_uri = 'linse-leiden-ts:3007'
|
||||
srbridge_uri = 'linse-leiden-ts:3008'
|
||||
|
||||
Mod('sea_main',
|
||||
'frappy_psi.sea.SeaClient',
|
||||
'main sea connection for leiden.config',
|
||||
config = 'leiden.config',
|
||||
service = 'main',
|
||||
)
|
||||
|
||||
for name in ['T3K', 'Tstill', 'T50mK', 'Tmxlow', 'Tmxhigh', 'Tmxcx', 'Tblueo',
|
||||
'Tpt50', 'Tpt3high', 'Tpt3low', 'Twhite', 'Tgreen']:
|
||||
mname = name.replace('T','T_')
|
||||
Mod(mname,
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io='sea_main',
|
||||
sea_object='tt',
|
||||
rel_paths=[name],
|
||||
value=Param(unit='K'),
|
||||
extra_modules = ['raw'],
|
||||
)
|
||||
Mod(name.replace('T', 'R_'),
|
||||
'frappy_psi.sea.SeaReadable', '',
|
||||
io='sea_main',
|
||||
value=Param(unit='Ohm'),
|
||||
single_module=f'{mname}.raw'
|
||||
)
|
||||
|
||||
#Mod('cmn',
|
||||
# 'frappy_psi.sea.SeaReadable', '',
|
||||
# io = 'sea_main',
|
||||
# sea_object = 'cmn',
|
||||
# extra_modules = ['u1', 'u2', 'temp'],
|
||||
#)
|
||||
|
||||
#Mod('T_cmn',
|
||||
# 'frappy_psi.sea.SeaReadable', '',
|
||||
# io='sea_main',
|
||||
# value=Param(unit='K'),
|
||||
# single_module='cmn.temp',
|
||||
#)
|
||||
|
||||
#Mod('V_fixp',
|
||||
# 'frappy_psi.sea.SeaReadable', '',
|
||||
# io='sea_main',
|
||||
# value=Param(unit='V'),
|
||||
# single_module='cmn.u2',
|
||||
#)
|
||||
|
||||
#Mod('V_cmn',
|
||||
# 'frappy_psi.sea.SeaReadable', '',
|
||||
# io='sea_main',
|
||||
# value=Param(unit='V'),
|
||||
# single_module='cmn.u1',
|
||||
#)
|
||||
|
||||
|
||||
Mod('tcs_io',
|
||||
'frappy_psi.tcs.IO',
|
||||
'tcs communication',
|
||||
uri=tcs_uri,
|
||||
)
|
||||
|
||||
Mod('still_htr',
|
||||
'frappy_psi.tcs.Heater',
|
||||
'still heater',
|
||||
io='tcs_io',
|
||||
channel=2,
|
||||
)
|
||||
|
||||
Mod('mix_io',
|
||||
'frappy_psi.dilhtr.IO',
|
||||
'dilhtr communication',
|
||||
uri=dilhtr_uri,
|
||||
)
|
||||
|
||||
Mod('mix_htr',
|
||||
'frappy_psi.dilhtr.WrappedHeater',
|
||||
'mixing chamber heater',
|
||||
io='mix_io',
|
||||
)
|
||||
|
||||
Mod('drive_mix',
|
||||
'frappy_psi.picontrol.PIctrl',
|
||||
'controlled mix ch. temperature',
|
||||
input_module = 'T_mxlow',
|
||||
output_module = 'mix_htr',
|
||||
output_min = 0,
|
||||
output_max = 0.02,
|
||||
p = 5,
|
||||
itime = 60,
|
||||
)
|
||||
|
||||
#Mod('drive_cmn',
|
||||
# 'frappy_psi.picontrol.PIctrl',
|
||||
# 'controlled cmn temperature',
|
||||
# input_module = 'T_cmn',
|
||||
# output_module = 'mix_htr',
|
||||
# output_min = 0,
|
||||
# output_max = 3e-2,
|
||||
# p = 2,
|
||||
# itime = 120,
|
||||
# )
|
||||
|
||||
#Mod('drive_fixp',
|
||||
# 'frappy_psi.picontrol.PI',
|
||||
# 'controlled fixpoint voltage',
|
||||
# value=Param(unit='V'),
|
||||
# input_module = 'V_fixp',
|
||||
# output_module = 'drive_mix',
|
||||
# output_min = 0.0,
|
||||
# output_max = 0.01,
|
||||
# p = 1,
|
||||
# itime = 120,
|
||||
# )
|
||||
|
||||
Mod('simio',
|
||||
'frappy_psi.bridge.BridgeIO',
|
||||
'communication to sim900',
|
||||
uri=srbridge_uri,
|
||||
)
|
||||
|
||||
Mod('res1',
|
||||
'frappy_psi.bridge.Resistance',
|
||||
'please add description',
|
||||
io='simio',
|
||||
port=1,
|
||||
)
|
||||
|
||||
Mod('res2',
|
||||
'frappy_psi.bridge.Resistance',
|
||||
'please add description',
|
||||
io='simio',
|
||||
port=3,
|
||||
)
|
||||
|
||||
Mod('phase1',
|
||||
'frappy_psi.bridge.Phase',
|
||||
'please add description',
|
||||
resistance='res1',
|
||||
)
|
||||
|
||||
Mod('phase2',
|
||||
'frappy_psi.bridge.Phase',
|
||||
'please add description',
|
||||
resistance='res2',
|
||||
)
|
||||
|
||||
|
||||
Mod('dev1',
|
||||
'frappy_psi.bridge.Deviation',
|
||||
'please add description',
|
||||
resistance='res1',
|
||||
)
|
||||
|
||||
Mod('dev2',
|
||||
'frappy_psi.bridge.Deviation',
|
||||
'please add description',
|
||||
resistance='res2',
|
||||
)
|
||||
|
||||
|
||||
Mod('vsource_io',
|
||||
'frappy_psi.k2601b.K2601bIO',
|
||||
'source meter',
|
||||
# uri = '129.129.156.90:5025',
|
||||
uri = k2601b_uri,
|
||||
)
|
||||
|
||||
|
||||
Mod('source',
|
||||
'frappy_psi.k2601b.SourceMeter'
|
||||
'',
|
||||
description = "keithley sourcemeter",
|
||||
mode = 2,
|
||||
vlimit = 0.5,
|
||||
ilimit = .0005,
|
||||
io = 'vsource_io',
|
||||
)
|
||||
|
||||
Mod('hvolt',
|
||||
'frappy_psi.k2601b.Voltage'
|
||||
'',
|
||||
description = "Heater Voltage",
|
||||
active = False,
|
||||
limit = 1.0,
|
||||
target = 0.0,
|
||||
sourcemeter = 'source',
|
||||
io = 'vsource_io',
|
||||
)
|
||||
|
||||
Mod('hcur',
|
||||
'frappy_psi.k2601b.Current'
|
||||
'',
|
||||
description = "Heater Current Source",
|
||||
active = True,
|
||||
limit = 0.0001,
|
||||
target = 0.0,
|
||||
sourcemeter = 'source',
|
||||
io = 'vsource_io',
|
||||
)
|
||||
|
||||
Mod('hres',
|
||||
'frappy_psi.k2601b.Resistivity'
|
||||
'',
|
||||
description = "Heater Resistance",
|
||||
io = 'vsource_io',
|
||||
)
|
||||
|
||||
Mod('hpow',
|
||||
'frappy_psi.k2601b.Power'
|
||||
'',
|
||||
description = "Heater Power",
|
||||
io = 'vsource_io',
|
||||
)
|
||||
29
cfg/sea/cp1000.addon.json
Normal file
29
cfg/sea/cp1000.addon.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{"cp2800": {"base": "/cp2800", "params": [
|
||||
{"path": "", "type": "bool", "readonly": false, "cmd": "cp2800", "kids": 27},
|
||||
{"path": "send", "type": "text", "readonly": false, "cmd": "cp2800 send", "visibility": 3},
|
||||
{"path": "status", "type": "text", "visibility": 3},
|
||||
{"path": "comp_running_hrs", "type": "float"},
|
||||
{"path": "cpu_t", "type": "float"},
|
||||
{"path": "motor_current_a", "type": "float"},
|
||||
{"path": "inp_water_t", "type": "float"},
|
||||
{"path": "inp_water_t_min", "type": "float"},
|
||||
{"path": "inp_water_t_max", "type": "float"},
|
||||
{"path": "out_water_t", "type": "float"},
|
||||
{"path": "out_water_t_min", "type": "float"},
|
||||
{"path": "out_water_t_max", "type": "float"},
|
||||
{"path": "helium_t", "type": "float"},
|
||||
{"path": "helium_t_min", "type": "float"},
|
||||
{"path": "helium_t_max", "type": "float"},
|
||||
{"path": "oil_t", "type": "float"},
|
||||
{"path": "oil_t_min", "type": "float"},
|
||||
{"path": "oil_t_max", "type": "float"},
|
||||
{"path": "high_side_p", "type": "float"},
|
||||
{"path": "high_side_p_min", "type": "float"},
|
||||
{"path": "high_side_p_max", "type": "float"},
|
||||
{"path": "high_side_p_avg", "type": "float"},
|
||||
{"path": "low_side_p", "type": "float"},
|
||||
{"path": "low_side_p_min", "type": "float"},
|
||||
{"path": "low_side_p_max", "type": "float"},
|
||||
{"path": "low_side_p_avg", "type": "float"},
|
||||
{"path": "high_side_delta_p_avg", "type": "float"},
|
||||
{"path": "high_side_bounce", "type": "float"}]}}
|
||||
14
cfg/sea/cp1000_cfg.py
Normal file
14
cfg/sea/cp1000_cfg.py
Normal file
@@ -0,0 +1,14 @@
|
||||
Node('cp1000.addon.sea.psi.ch',
|
||||
'''dry system''',
|
||||
)
|
||||
Mod('sea_addons',
|
||||
'frappy_psi.sea.SeaClient',
|
||||
'addons sea connection for cp1000.addon',
|
||||
config = 'cp1000.addon',
|
||||
service = 'addons',
|
||||
)
|
||||
Mod('cp2800',
|
||||
'frappy_psi.sea.SeaWritable', '',
|
||||
io = 'sea_addons',
|
||||
sea_object = 'cp2800',
|
||||
)
|
||||
213
cfg/sea/leiden.config.json
Normal file
213
cfg/sea/leiden.config.json
Normal file
@@ -0,0 +1,213 @@
|
||||
{"tt": {"base": "/tt", "params": [
|
||||
{"path": "", "type": "int", "kids": 18},
|
||||
{"path": "send", "type": "text", "readonly": false, "cmd": "tt send", "visibility": 3},
|
||||
{"path": "status", "type": "text", "visibility": 3},
|
||||
{"path": "autoscan", "type": "bool", "readonly": false, "cmd": "tt autoscan", "kids": 4},
|
||||
{"path": "autoscan/synchronized", "type": "bool", "readonly": false, "cmd": "tt autoscan/synchronized"},
|
||||
{"path": "autoscan/interval", "type": "text", "readonly": false, "cmd": "tt autoscan/interval"},
|
||||
{"path": "autoscan/pause", "type": "text", "readonly": false, "cmd": "tt autoscan/pause"},
|
||||
{"path": "autoscan/dwell", "type": "text", "readonly": false, "cmd": "tt autoscan/dwell"},
|
||||
{"path": "T3K", "type": "float", "kids": 14},
|
||||
{"path": "T3K/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt T3K/active"},
|
||||
{"path": "T3K/autorange", "type": "bool", "readonly": false, "cmd": "tt T3K/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "T3K/range", "type": "text", "readonly": false, "cmd": "tt T3K/range", "description": "resistance range in Ohm"},
|
||||
{"path": "T3K/range_num", "type": "int"},
|
||||
{"path": "T3K/excitation", "type": "text", "readonly": false, "cmd": "tt T3K/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "T3K/excitation_num", "type": "int"},
|
||||
{"path": "T3K/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "T3K/pause", "type": "int", "readonly": false, "cmd": "tt T3K/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "T3K/filter", "type": "int", "readonly": false, "cmd": "tt T3K/filter", "description": "filter average time [sec]"},
|
||||
{"path": "T3K/dwell", "type": "int", "readonly": false, "cmd": "tt T3K/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "T3K/status", "type": "text"},
|
||||
{"path": "T3K/curve", "type": "text", "readonly": false, "cmd": "tt T3K/curve", "kids": 1},
|
||||
{"path": "T3K/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt T3K/curve/points", "visibility": 3},
|
||||
{"path": "T3K/alarm", "type": "float", "readonly": false, "cmd": "tt T3K/alarm"},
|
||||
{"path": "T3K/raw", "type": "float"},
|
||||
{"path": "Tstill", "type": "float", "kids": 14},
|
||||
{"path": "Tstill/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tstill/active"},
|
||||
{"path": "Tstill/autorange", "type": "bool", "readonly": false, "cmd": "tt Tstill/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tstill/range", "type": "text", "readonly": false, "cmd": "tt Tstill/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tstill/range_num", "type": "int"},
|
||||
{"path": "Tstill/excitation", "type": "text", "readonly": false, "cmd": "tt Tstill/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tstill/excitation_num", "type": "int"},
|
||||
{"path": "Tstill/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tstill/pause", "type": "int", "readonly": false, "cmd": "tt Tstill/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tstill/filter", "type": "int", "readonly": false, "cmd": "tt Tstill/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tstill/dwell", "type": "int", "readonly": false, "cmd": "tt Tstill/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tstill/status", "type": "text"},
|
||||
{"path": "Tstill/curve", "type": "text", "readonly": false, "cmd": "tt Tstill/curve", "kids": 1},
|
||||
{"path": "Tstill/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tstill/curve/points", "visibility": 3},
|
||||
{"path": "Tstill/alarm", "type": "float", "readonly": false, "cmd": "tt Tstill/alarm"},
|
||||
{"path": "Tstill/raw", "type": "float"},
|
||||
{"path": "T50mK", "type": "float", "kids": 14},
|
||||
{"path": "T50mK/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt T50mK/active"},
|
||||
{"path": "T50mK/autorange", "type": "bool", "readonly": false, "cmd": "tt T50mK/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "T50mK/range", "type": "text", "readonly": false, "cmd": "tt T50mK/range", "description": "resistance range in Ohm"},
|
||||
{"path": "T50mK/range_num", "type": "int"},
|
||||
{"path": "T50mK/excitation", "type": "text", "readonly": false, "cmd": "tt T50mK/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "T50mK/excitation_num", "type": "int"},
|
||||
{"path": "T50mK/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "T50mK/pause", "type": "int", "readonly": false, "cmd": "tt T50mK/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "T50mK/filter", "type": "int", "readonly": false, "cmd": "tt T50mK/filter", "description": "filter average time [sec]"},
|
||||
{"path": "T50mK/dwell", "type": "int", "readonly": false, "cmd": "tt T50mK/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "T50mK/status", "type": "text"},
|
||||
{"path": "T50mK/curve", "type": "text", "readonly": false, "cmd": "tt T50mK/curve", "kids": 1},
|
||||
{"path": "T50mK/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt T50mK/curve/points", "visibility": 3},
|
||||
{"path": "T50mK/alarm", "type": "float", "readonly": false, "cmd": "tt T50mK/alarm"},
|
||||
{"path": "T50mK/raw", "type": "float"},
|
||||
{"path": "Tmxlow", "type": "float", "kids": 14},
|
||||
{"path": "Tmxlow/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tmxlow/active"},
|
||||
{"path": "Tmxlow/autorange", "type": "bool", "readonly": false, "cmd": "tt Tmxlow/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tmxlow/range", "type": "text", "readonly": false, "cmd": "tt Tmxlow/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tmxlow/range_num", "type": "int"},
|
||||
{"path": "Tmxlow/excitation", "type": "text", "readonly": false, "cmd": "tt Tmxlow/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tmxlow/excitation_num", "type": "int"},
|
||||
{"path": "Tmxlow/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tmxlow/pause", "type": "int", "readonly": false, "cmd": "tt Tmxlow/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tmxlow/filter", "type": "int", "readonly": false, "cmd": "tt Tmxlow/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tmxlow/dwell", "type": "int", "readonly": false, "cmd": "tt Tmxlow/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tmxlow/status", "type": "text"},
|
||||
{"path": "Tmxlow/curve", "type": "text", "readonly": false, "cmd": "tt Tmxlow/curve", "kids": 1},
|
||||
{"path": "Tmxlow/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tmxlow/curve/points", "visibility": 3},
|
||||
{"path": "Tmxlow/alarm", "type": "float", "readonly": false, "cmd": "tt Tmxlow/alarm"},
|
||||
{"path": "Tmxlow/raw", "type": "float"},
|
||||
{"path": "Tmxhigh", "type": "float", "kids": 14},
|
||||
{"path": "Tmxhigh/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tmxhigh/active"},
|
||||
{"path": "Tmxhigh/autorange", "type": "bool", "readonly": false, "cmd": "tt Tmxhigh/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tmxhigh/range", "type": "text", "readonly": false, "cmd": "tt Tmxhigh/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tmxhigh/range_num", "type": "int"},
|
||||
{"path": "Tmxhigh/excitation", "type": "text", "readonly": false, "cmd": "tt Tmxhigh/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tmxhigh/excitation_num", "type": "int"},
|
||||
{"path": "Tmxhigh/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tmxhigh/pause", "type": "int", "readonly": false, "cmd": "tt Tmxhigh/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tmxhigh/filter", "type": "int", "readonly": false, "cmd": "tt Tmxhigh/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tmxhigh/dwell", "type": "int", "readonly": false, "cmd": "tt Tmxhigh/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tmxhigh/status", "type": "text"},
|
||||
{"path": "Tmxhigh/curve", "type": "text", "readonly": false, "cmd": "tt Tmxhigh/curve", "kids": 1},
|
||||
{"path": "Tmxhigh/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tmxhigh/curve/points", "visibility": 3},
|
||||
{"path": "Tmxhigh/alarm", "type": "float", "readonly": false, "cmd": "tt Tmxhigh/alarm"},
|
||||
{"path": "Tmxhigh/raw", "type": "float"},
|
||||
{"path": "Tmxcx", "type": "float", "kids": 14},
|
||||
{"path": "Tmxcx/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tmxcx/active"},
|
||||
{"path": "Tmxcx/autorange", "type": "bool", "readonly": false, "cmd": "tt Tmxcx/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tmxcx/range", "type": "text", "readonly": false, "cmd": "tt Tmxcx/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tmxcx/range_num", "type": "int"},
|
||||
{"path": "Tmxcx/excitation", "type": "text", "readonly": false, "cmd": "tt Tmxcx/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tmxcx/excitation_num", "type": "int"},
|
||||
{"path": "Tmxcx/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tmxcx/pause", "type": "int", "readonly": false, "cmd": "tt Tmxcx/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tmxcx/filter", "type": "int", "readonly": false, "cmd": "tt Tmxcx/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tmxcx/dwell", "type": "int", "readonly": false, "cmd": "tt Tmxcx/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tmxcx/status", "type": "text"},
|
||||
{"path": "Tmxcx/curve", "type": "text", "readonly": false, "cmd": "tt Tmxcx/curve", "kids": 1},
|
||||
{"path": "Tmxcx/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tmxcx/curve/points", "visibility": 3},
|
||||
{"path": "Tmxcx/alarm", "type": "float", "readonly": false, "cmd": "tt Tmxcx/alarm"},
|
||||
{"path": "Tmxcx/raw", "type": "float"},
|
||||
{"path": "Tblueo", "type": "float", "kids": 14},
|
||||
{"path": "Tblueo/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tblueo/active"},
|
||||
{"path": "Tblueo/autorange", "type": "bool", "readonly": false, "cmd": "tt Tblueo/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tblueo/range", "type": "text", "readonly": false, "cmd": "tt Tblueo/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tblueo/range_num", "type": "int"},
|
||||
{"path": "Tblueo/excitation", "type": "text", "readonly": false, "cmd": "tt Tblueo/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tblueo/excitation_num", "type": "int"},
|
||||
{"path": "Tblueo/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tblueo/pause", "type": "int", "readonly": false, "cmd": "tt Tblueo/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tblueo/filter", "type": "int", "readonly": false, "cmd": "tt Tblueo/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tblueo/dwell", "type": "int", "readonly": false, "cmd": "tt Tblueo/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tblueo/status", "type": "text"},
|
||||
{"path": "Tblueo/curve", "type": "text", "readonly": false, "cmd": "tt Tblueo/curve", "kids": 1},
|
||||
{"path": "Tblueo/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tblueo/curve/points", "visibility": 3},
|
||||
{"path": "Tblueo/alarm", "type": "float", "readonly": false, "cmd": "tt Tblueo/alarm"},
|
||||
{"path": "Tblueo/raw", "type": "float"},
|
||||
{"path": "Tpt50", "type": "float", "kids": 14},
|
||||
{"path": "Tpt50/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tpt50/active"},
|
||||
{"path": "Tpt50/autorange", "type": "bool", "readonly": false, "cmd": "tt Tpt50/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tpt50/range", "type": "text", "readonly": false, "cmd": "tt Tpt50/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tpt50/range_num", "type": "int"},
|
||||
{"path": "Tpt50/excitation", "type": "text", "readonly": false, "cmd": "tt Tpt50/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tpt50/excitation_num", "type": "int"},
|
||||
{"path": "Tpt50/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tpt50/pause", "type": "int", "readonly": false, "cmd": "tt Tpt50/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tpt50/filter", "type": "int", "readonly": false, "cmd": "tt Tpt50/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tpt50/dwell", "type": "int", "readonly": false, "cmd": "tt Tpt50/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tpt50/status", "type": "text"},
|
||||
{"path": "Tpt50/curve", "type": "text", "readonly": false, "cmd": "tt Tpt50/curve", "kids": 1},
|
||||
{"path": "Tpt50/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tpt50/curve/points", "visibility": 3},
|
||||
{"path": "Tpt50/alarm", "type": "float", "readonly": false, "cmd": "tt Tpt50/alarm"},
|
||||
{"path": "Tpt50/raw", "type": "float"},
|
||||
{"path": "Tpt3high", "type": "float", "kids": 14},
|
||||
{"path": "Tpt3high/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tpt3high/active"},
|
||||
{"path": "Tpt3high/autorange", "type": "bool", "readonly": false, "cmd": "tt Tpt3high/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tpt3high/range", "type": "text", "readonly": false, "cmd": "tt Tpt3high/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tpt3high/range_num", "type": "int"},
|
||||
{"path": "Tpt3high/excitation", "type": "text", "readonly": false, "cmd": "tt Tpt3high/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tpt3high/excitation_num", "type": "int"},
|
||||
{"path": "Tpt3high/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tpt3high/pause", "type": "int", "readonly": false, "cmd": "tt Tpt3high/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tpt3high/filter", "type": "int", "readonly": false, "cmd": "tt Tpt3high/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tpt3high/dwell", "type": "int", "readonly": false, "cmd": "tt Tpt3high/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tpt3high/status", "type": "text"},
|
||||
{"path": "Tpt3high/curve", "type": "text", "readonly": false, "cmd": "tt Tpt3high/curve", "kids": 1},
|
||||
{"path": "Tpt3high/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tpt3high/curve/points", "visibility": 3},
|
||||
{"path": "Tpt3high/alarm", "type": "float", "readonly": false, "cmd": "tt Tpt3high/alarm"},
|
||||
{"path": "Tpt3high/raw", "type": "float"},
|
||||
{"path": "Tpt3low", "type": "float", "kids": 14},
|
||||
{"path": "Tpt3low/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tpt3low/active"},
|
||||
{"path": "Tpt3low/autorange", "type": "bool", "readonly": false, "cmd": "tt Tpt3low/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tpt3low/range", "type": "text", "readonly": false, "cmd": "tt Tpt3low/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tpt3low/range_num", "type": "int"},
|
||||
{"path": "Tpt3low/excitation", "type": "text", "readonly": false, "cmd": "tt Tpt3low/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tpt3low/excitation_num", "type": "int"},
|
||||
{"path": "Tpt3low/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tpt3low/pause", "type": "int", "readonly": false, "cmd": "tt Tpt3low/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tpt3low/filter", "type": "int", "readonly": false, "cmd": "tt Tpt3low/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tpt3low/dwell", "type": "int", "readonly": false, "cmd": "tt Tpt3low/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tpt3low/status", "type": "text"},
|
||||
{"path": "Tpt3low/curve", "type": "text", "readonly": false, "cmd": "tt Tpt3low/curve", "kids": 1},
|
||||
{"path": "Tpt3low/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tpt3low/curve/points", "visibility": 3},
|
||||
{"path": "Tpt3low/alarm", "type": "float", "readonly": false, "cmd": "tt Tpt3low/alarm"},
|
||||
{"path": "Tpt3low/raw", "type": "float"},
|
||||
{"path": "Twhite", "type": "float", "kids": 14},
|
||||
{"path": "Twhite/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Twhite/active"},
|
||||
{"path": "Twhite/autorange", "type": "bool", "readonly": false, "cmd": "tt Twhite/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Twhite/range", "type": "text", "readonly": false, "cmd": "tt Twhite/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Twhite/range_num", "type": "int"},
|
||||
{"path": "Twhite/excitation", "type": "text", "readonly": false, "cmd": "tt Twhite/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Twhite/excitation_num", "type": "int"},
|
||||
{"path": "Twhite/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Twhite/pause", "type": "int", "readonly": false, "cmd": "tt Twhite/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Twhite/filter", "type": "int", "readonly": false, "cmd": "tt Twhite/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Twhite/dwell", "type": "int", "readonly": false, "cmd": "tt Twhite/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Twhite/status", "type": "text"},
|
||||
{"path": "Twhite/curve", "type": "text", "readonly": false, "cmd": "tt Twhite/curve", "kids": 1},
|
||||
{"path": "Twhite/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Twhite/curve/points", "visibility": 3},
|
||||
{"path": "Twhite/alarm", "type": "float", "readonly": false, "cmd": "tt Twhite/alarm"},
|
||||
{"path": "Twhite/raw", "type": "float"},
|
||||
{"path": "Tgreen", "type": "float", "kids": 14},
|
||||
{"path": "Tgreen/active", "type": "enum", "enum": {"inactive": 0, "active": 1}, "readonly": false, "cmd": "tt Tgreen/active"},
|
||||
{"path": "Tgreen/autorange", "type": "bool", "readonly": false, "cmd": "tt Tgreen/autorange", "description": "autorange (common for all channels)"},
|
||||
{"path": "Tgreen/range", "type": "text", "readonly": false, "cmd": "tt Tgreen/range", "description": "resistance range in Ohm"},
|
||||
{"path": "Tgreen/range_num", "type": "int"},
|
||||
{"path": "Tgreen/excitation", "type": "text", "readonly": false, "cmd": "tt Tgreen/excitation", "description": "excitation with unit, i.e. 2uV or 3pA"},
|
||||
{"path": "Tgreen/excitation_num", "type": "int"},
|
||||
{"path": "Tgreen/excitation_mode", "type": "enum", "enum": {"voltage": 0, "current": 1, "off": 2}},
|
||||
{"path": "Tgreen/pause", "type": "int", "readonly": false, "cmd": "tt Tgreen/pause", "description": "pause time [sec] after channel change"},
|
||||
{"path": "Tgreen/filter", "type": "int", "readonly": false, "cmd": "tt Tgreen/filter", "description": "filter average time [sec]"},
|
||||
{"path": "Tgreen/dwell", "type": "int", "readonly": false, "cmd": "tt Tgreen/dwell", "description": "dwell time [sec]. Total time per channel: pause + filter + dwell"},
|
||||
{"path": "Tgreen/status", "type": "text"},
|
||||
{"path": "Tgreen/curve", "type": "text", "readonly": false, "cmd": "tt Tgreen/curve", "kids": 1},
|
||||
{"path": "Tgreen/curve/points", "type": "floatvarar", "readonly": false, "cmd": "tt Tgreen/curve/points", "visibility": 3},
|
||||
{"path": "Tgreen/alarm", "type": "float", "readonly": false, "cmd": "tt Tgreen/alarm"},
|
||||
{"path": "Tgreen/raw", "type": "float"},
|
||||
{"path": "analog2", "type": "float", "readonly": false, "cmd": "tt analog2"},
|
||||
{"path": "remote", "type": "bool"},
|
||||
{"path": "display", "type": "text", "readonly": false, "cmd": "tt display"}]},
|
||||
|
||||
"cmn": {"base": "/cmn", "params": [
|
||||
{"path": "", "type": "none", "kids": 6},
|
||||
{"path": "send", "type": "text", "readonly": false, "cmd": "cmn send", "visibility": 3},
|
||||
{"path": "status", "type": "text", "visibility": 3},
|
||||
{"path": "u1", "type": "float"},
|
||||
{"path": "temp", "type": "float"},
|
||||
{"path": "u2", "type": "float"},
|
||||
{"path": "chan", "type": "enum", "enum": {"auto": 0, "chan1": 1, "chan2": 2}, "readonly": false, "cmd": "cmn chan"}]}}
|
||||
@@ -1,160 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# *****************************************************************************
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Module authors:
|
||||
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||
# *****************************************************************************
|
||||
"""Andeen Hagerling capacitance bridge
|
||||
|
||||
two modules: the capacitance itself and the loss angle
|
||||
|
||||
in the configuration file, only the capacitance module needs to be configured,
|
||||
while the loss module will be created automatically.
|
||||
|
||||
the name of the loss module may be configured, or disabled by choosing
|
||||
an empty name
|
||||
"""
|
||||
|
||||
from frappy.core import FloatRange, HasIO, Parameter, Readable, StringIO, nopoll, \
|
||||
Attached, Property, StringType, Writable
|
||||
from frappy.dynamic import Pinata
|
||||
|
||||
|
||||
class Ah2700IO(StringIO):
|
||||
end_of_line = '\r\n'
|
||||
timeout = 5
|
||||
|
||||
|
||||
class Capacitance(HasIO, Pinata, Readable):
|
||||
value = Parameter('capacitance', FloatRange(unit='pF'))
|
||||
freq = Parameter('frequency', FloatRange(unit='Hz'), readonly=False, default=0)
|
||||
voltage = Parameter('voltage', FloatRange(unit='V'), readonly=False, default=0)
|
||||
loss_name = Property('''name of loss module (default: <name>_loss)
|
||||
|
||||
configure '' to disable the creation of the loss module
|
||||
''',
|
||||
StringType(), default='$_loss')
|
||||
freq_name = Property('''name of freq module
|
||||
|
||||
default: not created
|
||||
''',
|
||||
StringType(), default='')
|
||||
|
||||
ioClass = Ah2700IO
|
||||
loss = 0 # not a parameter
|
||||
|
||||
def scanModules(self):
|
||||
if self.loss_name:
|
||||
# if loss_name is not empty, we tell the framework to create
|
||||
# a module for the loss with this name, and config below
|
||||
yield self.loss_name.replace('$', self.name), {
|
||||
'cls': Loss,
|
||||
'description': f'loss value of {self.name}',
|
||||
'cap': self.name}
|
||||
if self.freq_name:
|
||||
yield self.freq_name.replace('$', self.name), {
|
||||
'cls': Freq,
|
||||
'description': f'freq module of {self.name}',
|
||||
'cap': self.name}
|
||||
|
||||
def parse_reply(self, reply):
|
||||
if reply.startswith('SI'): # this is an echo
|
||||
self.communicate('SERIAL ECHO OFF')
|
||||
reply = self.communicate('SI')
|
||||
if not reply.startswith('F='): # this is probably an error message like "LOSS TOO HIGH"
|
||||
self.status = self.Status.ERROR, reply
|
||||
return self.value
|
||||
self.status = self.Status.IDLE, ''
|
||||
# examples of replies:
|
||||
# 'F= 1000.0 HZ C= 0.000001 PF L> 0.0 DS V= 15.0 V'
|
||||
# 'F= 1000.0 HZ C= 0.0000059 PF L=-0.4 DS V= 15.0 V OVEN'
|
||||
# 'LOSS TOO HIGH'
|
||||
# make sure there is always a space after '=' and '>'
|
||||
# split() ignores multiple white space
|
||||
reply = reply.replace('=', '= ').replace('>', '> ').split()
|
||||
_, freq, _, _, cap, _, _, loss, lossunit, _, volt = reply[:11]
|
||||
self.freq = float(freq)
|
||||
self.voltage = float(volt)
|
||||
if lossunit == 'DS':
|
||||
self.loss = float(loss)
|
||||
else: # the unit was wrong, we want DS = tan(delta), not NS = nanoSiemens
|
||||
reply = self.communicate('UN DS').split() # UN DS returns a reply similar to SI
|
||||
try:
|
||||
self.loss = reply[7]
|
||||
except IndexError:
|
||||
pass # don't worry, loss will be updated next time
|
||||
return float(cap)
|
||||
|
||||
def read_value(self):
|
||||
return self.parse_reply(self.communicate('SI')) # SI = single trigger
|
||||
|
||||
@nopoll
|
||||
def read_freq(self):
|
||||
self.read_value()
|
||||
return self.freq
|
||||
|
||||
@nopoll
|
||||
def read_voltage(self):
|
||||
self.read_value()
|
||||
return self.voltage
|
||||
|
||||
def write_freq(self, value):
|
||||
self.value = self.parse_reply(self.communicate(f'FR {value:g};SI'))
|
||||
return self.freq
|
||||
|
||||
def write_voltage(self, value):
|
||||
self.value = self.parse_reply(self.communicate(f'V {value:g};SI'))
|
||||
return self.voltage
|
||||
|
||||
|
||||
class Loss(Readable):
|
||||
cap = Attached()
|
||||
value = Parameter('loss', FloatRange(unit='deg'), default=0)
|
||||
|
||||
def initModule(self):
|
||||
super().initModule()
|
||||
self.cap.registerCallbacks(self, ['status']) # auto update status
|
||||
|
||||
def update_value(self, _):
|
||||
# value is always changed shortly after loss
|
||||
self.value = self.cap.loss
|
||||
|
||||
@nopoll
|
||||
def read_value(self):
|
||||
self.cap.read_value()
|
||||
return self.cap.loss
|
||||
|
||||
|
||||
class Freq(Writable):
|
||||
cap = Attached()
|
||||
value = Parameter('', FloatRange(unit='Hz'), default=0)
|
||||
|
||||
def initModule(self):
|
||||
super().initModule()
|
||||
self.cap.registerCallbacks(self, ['status']) # auto update status
|
||||
|
||||
def update_value(self, _):
|
||||
# value is always changed shortly after freq
|
||||
self.value = self.cap.freq
|
||||
|
||||
@nopoll
|
||||
def read_value(self):
|
||||
self.cap.read_value()
|
||||
return self.cap.freq
|
||||
|
||||
def write_target(self, target):
|
||||
self.cap.write_freq(target)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
# *****************************************************************************
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -19,73 +18,50 @@
|
||||
# *****************************************************************************
|
||||
"""Andeen Hagerling capacitance bridge
|
||||
|
||||
two modules: the capacitance itself and the loss angle
|
||||
creates up to two additional modules for 'loss' and 'freq'
|
||||
|
||||
in the configuration file, only the capacitance module needs to be configured,
|
||||
while the loss module will be created automatically.
|
||||
|
||||
the name of the loss module may be configured, or disabled by choosing
|
||||
an empty name
|
||||
the name of the loss (and freq) module may be configured, or disabled by
|
||||
choosing an empty name
|
||||
"""
|
||||
|
||||
import re
|
||||
import time
|
||||
import math
|
||||
from frappy.core import FloatRange, HasIO, Parameter, Readable, StringIO, \
|
||||
Attached, Property, StringType, Command, Writable, IntRange, BUSY, IDLE, WARN, ERROR
|
||||
import threading
|
||||
from frappy.core import HasIO, Parameter, Readable, StringIO, \
|
||||
Attached, Property, Command, Writable, BUSY, IDLE, WARN
|
||||
from frappy.datatypes import FloatRange, IntRange, StringType, TupleOf
|
||||
from frappy.modules import Acquisition
|
||||
from frappy.dynamic import Pinata
|
||||
from frappy.errors import ProgrammingError
|
||||
from frappy.lib import clamp
|
||||
from frappy.errors import ProgrammingError, IsBusyError
|
||||
|
||||
|
||||
class IO(StringIO):
|
||||
end_of_line = '\r\n'
|
||||
timeout = 1
|
||||
# default_settings = {'timeout': 0.1}
|
||||
last_command = None
|
||||
|
||||
# @Command(result=StringType())
|
||||
# def readline(self):
|
||||
# """async read"""
|
||||
# with self._lock:
|
||||
# reply = self._conn.readline()
|
||||
# if reply:
|
||||
# result = reply.decode(self.encoding)
|
||||
# self.comLog('< %s', result)
|
||||
# return result
|
||||
# return ''
|
||||
#
|
||||
# @Command(StringType())
|
||||
# def writeline(self, command):
|
||||
# """no flush before"""
|
||||
# cmd = command.encode(self.encoding)
|
||||
# self.check_connection()
|
||||
# try:
|
||||
# self.comLog('> %s', command)
|
||||
# self._conn.send(cmd + self._eol_write)
|
||||
# self.last_command = command
|
||||
# except ConnectionClosed:
|
||||
# self.closeConnection()
|
||||
# raise CommunicationFailedError('disconnected') from None
|
||||
# except Exception as e:
|
||||
# if self._conn is None:
|
||||
# raise SilentError('disconnected') from None
|
||||
# if repr(e) != self._last_error:
|
||||
# self._last_error = repr(e)
|
||||
# self.log.error(self._last_error)
|
||||
# raise SilentError(repr(e)) from e
|
||||
end_of_line = ('\r\n', '\r')
|
||||
# for writing, '\r\n' also accepted on AH2700
|
||||
# for reading, '\r\n' would be correct, but '\r' does also works
|
||||
# when stripping the reply
|
||||
timeout = 5
|
||||
|
||||
@Command(StringType(), result=StringType())
|
||||
def communicate(self, command, noreply=False):
|
||||
"""communicate and save the last command"""
|
||||
# this is also called by writeline
|
||||
self.last_time = time.time()
|
||||
return super().communicate(command, noreply)
|
||||
reply = super().communicate(command, noreply)
|
||||
return reply and reply.strip()
|
||||
|
||||
|
||||
class AH2550(HasIO, Pinata, Acquisition):
|
||||
CONTINUOUS = 0
|
||||
STARTING = 1
|
||||
RUNNING = 2
|
||||
FINISHED = 3
|
||||
|
||||
|
||||
class AHBase(HasIO, Pinata, Acquisition):
|
||||
value = Parameter('capacitance', FloatRange(unit='pF'))
|
||||
freq = Parameter('frequency', FloatRange(unit='Hz'), default=1000)
|
||||
voltage = Parameter('upper voltage limit',
|
||||
FloatRange(0, 15, unit='V', fmtstr='%.1f'),
|
||||
readonly=False, default=0)
|
||||
@@ -93,127 +69,31 @@ class AH2550(HasIO, Pinata, Acquisition):
|
||||
FloatRange(unit=''), default=0)
|
||||
averexp = Parameter('base 2 exponent of goal',
|
||||
IntRange(0, 15), readonly=False, default=0)
|
||||
goal = Parameter('number of samples to average',
|
||||
FloatRange(0, 50000, unit='samples'),
|
||||
readonly=False, default=0)
|
||||
goal = Parameter('value for averexp for the next go()',
|
||||
IntRange(0, 15), readonly=False, default=0)
|
||||
meas_time = Parameter('measured measuring time',
|
||||
FloatRange(unit='s', fmtstr='%.1f'), default=0)
|
||||
loss_module = Property('''name of loss module (default: <name>_loss)
|
||||
FloatRange(unit='s', fmtstr='%.4g'), default=0)
|
||||
calculated_time = Parameter('calculated measuring time',
|
||||
FloatRange(unit='s', fmtstr='%.4g'), default=0)
|
||||
loss_module = Property(
|
||||
'''name of loss module (default: <name>_loss)
|
||||
|
||||
configure '' to disable the creation of the loss module
|
||||
''',
|
||||
StringType(), default='')
|
||||
pollinterval = Parameter(export=False, value=0.1)
|
||||
''', StringType(), default='')
|
||||
pollinterval = Parameter(datatype=FloatRange(0.001, 1),
|
||||
export=False, value=0.001)
|
||||
export = True # for a Pinata module, the default is False!
|
||||
ioClass = IO
|
||||
MODEL = 'AH2550'
|
||||
PATTERN = [
|
||||
r'AVERAGE *AVEREXP=(?P<averexp>[0-9]*)',
|
||||
r'VOLTAGE HIGHEST *(?P<voltage>[0-9.E+-]+)',
|
||||
]
|
||||
MEAS_PAT = (
|
||||
r'C= *(?P<cap>[0-9.E+-]+) *PF '
|
||||
r'L= *(?P<loss>[0-9.E+-]+) *(?P<lossunit>[A-Z]*) '
|
||||
f'V= *(?P<voltage>[0-9.E+-]+) *V *(?P<error>.*)$'
|
||||
# <volt> must not collide with <voltage>
|
||||
)
|
||||
COMMANDS = ['AV', 'VO', 'SI' ,'SH']
|
||||
_started = 0
|
||||
_meas_state = 0
|
||||
_todo = None
|
||||
COMMANDS = ['AV', 'VO', 'SI', 'SH', 'FR']
|
||||
_error = ''
|
||||
|
||||
def initModule(self):
|
||||
self.io.setProperty('identification',
|
||||
[('\r\nSERIAL ECHO OFF;SH MODEL', f'MODEL/OPTIONS *{self.MODEL}')])
|
||||
super().initModule()
|
||||
self.log.info('INIT')
|
||||
pattern = self.PATTERN + [self.MEAS_PAT]
|
||||
self.pattern = {p[:2]: re.compile(p) for p in pattern}
|
||||
if len(self.pattern) != len(pattern):
|
||||
raise ProgrammingError('need more than two letters to distinguish patterns')
|
||||
self.echo = re.compile('|'.join(self.COMMANDS))
|
||||
# first commands:
|
||||
# UN DS does also return the resukts of the last measurement (including the frequency for AH2700)
|
||||
self._todo = {'averexp': 'SH AV', '<unit>': 'UN DS'}
|
||||
|
||||
def doPoll(self):
|
||||
if self.io.last_time: # a command was sent
|
||||
self._started = 0 # trigger start
|
||||
reply = self.io.readline(0)
|
||||
if reply:
|
||||
# parse reply of (here unknown) command
|
||||
self.io.last_time = 0
|
||||
pattern = self.pattern.get(reply[:2])
|
||||
if pattern:
|
||||
match = pattern.match(reply)
|
||||
if not match:
|
||||
self.log.warning('unexpected reply syntax: %r', reply)
|
||||
return
|
||||
values = match.groupdict()
|
||||
if len(values) == 1:
|
||||
key, value = next(iter(values.items()))
|
||||
getattr(self, f'update_{key}')(float(value))
|
||||
return
|
||||
self.update_meas(**values)
|
||||
return
|
||||
if self.echo.match(reply):
|
||||
# this is probably an echo
|
||||
# we may have lost connection, so query again averexp
|
||||
self.writeline('\r\nSERIAL ECHO OFF;SH AV')
|
||||
return
|
||||
self.log.warning('unknown reply %r', reply)
|
||||
return
|
||||
now = time.time()
|
||||
if now < self.io.last_time + 1:
|
||||
# send no more commands before we have the reply of the previous
|
||||
return
|
||||
if self._todo:
|
||||
# we have parameters to be changed
|
||||
# this will interrupt the current measurement
|
||||
command = self._todo.pop(next(iter(self._todo)))
|
||||
self.io.writeline(command)
|
||||
return
|
||||
if self._started:
|
||||
# we are measuring, the last command was SI
|
||||
return
|
||||
# nothing else to do - we start measuring
|
||||
if self._meas_state == 1:
|
||||
self._meas_state = 2
|
||||
self.status = BUSY, 'measuring'
|
||||
self.trigger_measurement()
|
||||
|
||||
def trigger_measurement(self):
|
||||
self._started = time.time()
|
||||
self.writeline('SI')
|
||||
self.io.last_time = 0 # do not retrigger again
|
||||
|
||||
def update_meas(self, cap, loss, lossunit, voltage, error, freq=None):
|
||||
"""update given arguments (these are strings!)"""
|
||||
now = time.time()
|
||||
self.meas_time = now - self._started
|
||||
self.value = float(cap)
|
||||
self.voltage = float(voltage)
|
||||
self._error = error
|
||||
if self._meas_state == 2:
|
||||
self._meas_state = 0
|
||||
if self._error:
|
||||
self.status = WARN, self._error
|
||||
else:
|
||||
self.status = IDLE, ''
|
||||
if lossunit != 'DS':
|
||||
self.io.writeline('UN DS') # this will trigger a measuremement reply
|
||||
return
|
||||
self.loss = float(loss)
|
||||
self.trigger_measurement()
|
||||
|
||||
def update_lossunit(self, unit):
|
||||
if unit != 'DS':
|
||||
self.log.warning('can not change unit to DS')
|
||||
|
||||
def update_averexp(self, averexp):
|
||||
self.averexp = int(averexp)
|
||||
self.goal = 2 ** self.averexp
|
||||
_last_start = None
|
||||
_params = None
|
||||
_mode = CONTINUOUS # or RUNNING or FINISHED
|
||||
_cont_deadline = 0 # when to switch back to continuous after finished
|
||||
_averexp_deadline = 0 # to make sure averexp is polled periodically
|
||||
# to be overridden:
|
||||
PATTERN = None # a list of patterns to parse replies
|
||||
MEAS_PAT = None # the pattern to parse the measurement reply
|
||||
|
||||
def scanModules(self):
|
||||
if self.loss_module:
|
||||
@@ -224,24 +104,192 @@ class AH2550(HasIO, Pinata, Acquisition):
|
||||
'description': f'loss value of {self.name}',
|
||||
'cap': self.name}
|
||||
|
||||
def initModule(self):
|
||||
self.io.setProperty('identification',
|
||||
[('\rSERIAL ECHO OFF;SH MODEL',
|
||||
'ILLEGAL WORD: MODEL')])
|
||||
super().initModule()
|
||||
pattern = self.PATTERN + [self.MEAS_PAT]
|
||||
self.pattern = {p[:2]: re.compile(p) for p in pattern}
|
||||
if len(self.pattern) != len(pattern):
|
||||
raise ProgrammingError('need more than two letters '
|
||||
'to distinguish patterns')
|
||||
self.echo = re.compile('|'.join(self.COMMANDS))
|
||||
self._params = {}
|
||||
self._lock = threading.RLock()
|
||||
|
||||
def initialReads(self):
|
||||
# UN 2 does also return the results of the last measurement
|
||||
# (including the frequency for AH2700)
|
||||
self.io.writeline('SH FR;UN 2')
|
||||
self.freq = self.interprete('freq')
|
||||
self.verify_averexp()
|
||||
self.goal = self.averexp
|
||||
self.single_meas()
|
||||
|
||||
def interprete(self, wait_for=None, tmo=None):
|
||||
"""
|
||||
|
||||
:param wait_for: name of parameter to wait for or None to wait
|
||||
for measurement
|
||||
:param tmo:
|
||||
:return:
|
||||
"""
|
||||
if tmo is None:
|
||||
tmo = self.io.timeout
|
||||
reply = self.io.readline(tmo)
|
||||
now = time.time()
|
||||
while reply:
|
||||
pattern = self.pattern.get(reply[:2])
|
||||
if pattern:
|
||||
match = pattern.match(reply)
|
||||
if not match:
|
||||
self.log.warning('unexpected reply syntax: %r', reply)
|
||||
break
|
||||
values = match.groupdict()
|
||||
if len(values) == 1:
|
||||
key, value = next(iter(values.items()))
|
||||
self._params[key] = float(value)
|
||||
else:
|
||||
self._params['meas'] = values
|
||||
elif self.echo.match(reply):
|
||||
# this is probably an echo
|
||||
# we may have lost connection, so query again averexp
|
||||
self.writeline('\r\nSERIAL ECHO OFF;SH AV')
|
||||
elif reply:
|
||||
self.log.warning('unknown reply %r', reply)
|
||||
if (wait_for or 'meas') in self._params:
|
||||
break
|
||||
reply = self.io.readline(tmo)
|
||||
self.log.debug('doPoll %r params %r wait_for %r %d', reply,
|
||||
list(self._params), wait_for, self._mode)
|
||||
result = self._params.pop(wait_for, None)
|
||||
if self._mode == FINISHED and now > self._cont_deadline:
|
||||
self._mode = CONTINUOUS
|
||||
self.status = IDLE, ''
|
||||
self.single_meas()
|
||||
return
|
||||
if result is None and wait_for:
|
||||
self.log.info(f'missing reply for {wait_for}')
|
||||
return getattr(self, wait_for, None)
|
||||
return result
|
||||
|
||||
def change(self, short, value, param):
|
||||
if self._mode == RUNNING:
|
||||
raise IsBusyError('can not change parameters while measuring')
|
||||
with self._lock:
|
||||
self.io.writeline(f'{short} {value};SH {short}')
|
||||
result = self.interprete(param)
|
||||
self.retrigger_meas()
|
||||
return result
|
||||
|
||||
def retrigger_meas(self):
|
||||
if self._mode == CONTINUOUS:
|
||||
self.single_meas()
|
||||
|
||||
def single_meas(self):
|
||||
self._last_start = time.time()
|
||||
self.writeline('SI')
|
||||
|
||||
def doPoll(self):
|
||||
# this polls measurement results
|
||||
# we can not do polling of other parameters, as they would
|
||||
# interrupt measurements. averexp needs a special treatment
|
||||
self.interprete(tmo=1)
|
||||
with self._lock:
|
||||
for param in list(self._params):
|
||||
value = self._params.pop(param, None)
|
||||
if param == 'meas':
|
||||
self.update_meas(**value)
|
||||
self.retrigger_meas()
|
||||
elif param == 'averexp':
|
||||
self.update_averexp(value)
|
||||
elif param == 'freq':
|
||||
self.update_freq(value)
|
||||
elif param == 'voltage':
|
||||
self.voltage = value
|
||||
|
||||
def update_freq(self, value):
|
||||
self.freq = value
|
||||
self._calculate_time(self.averexp, value)
|
||||
|
||||
def update_averexp(self, value):
|
||||
self.averexp = value
|
||||
self._averexp_deadline = time.time() + 15
|
||||
self._calculate_time(value, self.freq)
|
||||
|
||||
def update_meas(self, cap, loss, lossunit, voltage, error, freq=None):
|
||||
"""update given arguments (these are strings!)"""
|
||||
self._error = error
|
||||
if self._error:
|
||||
status = WARN, self._error
|
||||
else:
|
||||
status = IDLE, '' if self._mode == CONTINUOUS else 'finished'
|
||||
if status != self.status:
|
||||
self.status = status
|
||||
now = time.time()
|
||||
if self._mode == RUNNING:
|
||||
self._cont_deadline = now + 5
|
||||
self._mode = FINISHED
|
||||
if freq:
|
||||
self.freq = float(freq)
|
||||
self._calculate_time(self.averexp, self.freq)
|
||||
self.value = float(cap)
|
||||
self.voltage = float(voltage)
|
||||
if lossunit != self.UNIT:
|
||||
if self._last_start == 0:
|
||||
self.log.warning('change unit to %s failed', self.UNIT)
|
||||
else:
|
||||
self.io.writeline('UN 2')
|
||||
# this will trigger a measurement reply
|
||||
# skip calculation of meas_time while interpreting result
|
||||
self._last_start = 0
|
||||
self.interprete('meas')
|
||||
self.retrigger_meas()
|
||||
return
|
||||
if self._last_start:
|
||||
self.meas_time = now - self._last_start
|
||||
self._last_start = 0
|
||||
if now > self._averexp_deadline and self._mode == CONTINUOUS:
|
||||
self.verify_averexp()
|
||||
self.loss = float(loss)
|
||||
|
||||
def write_voltage(self, value):
|
||||
self._todo['voltage'] = f'VO {value:g};SH VO'
|
||||
return round(value, 1)
|
||||
return round(self.change('VO', f'{value:.1f}', 'voltage'), 1)
|
||||
|
||||
def write_averexp(self, value):
|
||||
self._todo['averexp'] = f'AV {value};SH AV'
|
||||
self.goal = 2 ** value
|
||||
self.update_averexp(self.change('AV', f'{value}', 'averexp'))
|
||||
|
||||
def write_goal(self, value):
|
||||
self.averexp = clamp(0, 15, round(math.log2(value)))
|
||||
self._todo['averexp'] = f'AV {self.averexp};SH AV'
|
||||
return 2 ** self.averexp
|
||||
def verify_averexp(self):
|
||||
# we do not want to use read_averexp for this,
|
||||
# as it will stop the measurement when polled
|
||||
self.io.writeline('SH AV')
|
||||
self.update_averexp(self.interprete('averexp'))
|
||||
|
||||
def _calculate_time(self, averexp, freq):
|
||||
self.calculated_time = self.calculate_time(averexp, freq)
|
||||
|
||||
def go(self):
|
||||
"""start acquisition"""
|
||||
prevmode = self._mode
|
||||
self._mode = STARTING
|
||||
if prevmode != FINISHED or time.time() > self._averexp_deadline:
|
||||
# this also makes sure we catch a previous meas reply
|
||||
self.verify_averexp()
|
||||
if self.averexp != self.goal:
|
||||
self.log.info('changed averexp')
|
||||
self.write_averexp(self.goal)
|
||||
self.status = BUSY, 'started'
|
||||
self._started = 0 # interrupt current measurement
|
||||
self._meas_state = 1 # retrigger a measurement
|
||||
self.single_meas()
|
||||
self._mode = RUNNING
|
||||
|
||||
def stop(self):
|
||||
"""stops measurement"""
|
||||
if self._mode == RUNNING:
|
||||
self.verify_averexp()
|
||||
self.status = WARN, 'stopped'
|
||||
self._mode = FINISHED
|
||||
self._cont_deadline = time.time() + 5
|
||||
|
||||
|
||||
class Loss(Readable):
|
||||
@@ -268,25 +316,71 @@ class Freq(Writable):
|
||||
self.cap.addCallback('freq', self.update_freq) # auto update status
|
||||
|
||||
def update_freq(self, freq):
|
||||
self.value = float(freq)
|
||||
self.value = freq
|
||||
|
||||
def write_target(self, target):
|
||||
self.cap.write_freq(target)
|
||||
|
||||
|
||||
class AH2700(AH2550):
|
||||
MODEL = 'AH2700'
|
||||
freq = Parameter('frequency',
|
||||
FloatRange(50, 20000, unit='Hz', fmtstr='%.1f'),
|
||||
readonly=False, default=50)
|
||||
class AH2550(AHBase):
|
||||
PATTERN = [
|
||||
r'AVERAGE_AVEREXP *(?P<averexp>[0-9]*)',
|
||||
r'VOLTAGE_HIGHEST *(?P<voltage>[0-9.E+-]+)',
|
||||
r'FREQUENCY *(?P<freq>[0-9.E+-]+)',
|
||||
]
|
||||
MEAS_PAT = (
|
||||
r'C= *(?P<cap>[0-9.E+-]+) *PF,'
|
||||
r'L= *(?P<loss>[0-9.E+-]+) *(?P<lossunit>[A-Z]*),'
|
||||
r'V= *(?P<voltage>[0-9.E+-]+) *V,A,*(?P<error>.*)$'
|
||||
)
|
||||
UNIT = 'DF'
|
||||
|
||||
# empirically determined - may vary with noise
|
||||
# differs drastically from the table in the manual
|
||||
MEAS_TIME_CONST = [0.2, 0.3, 0.4, 1.0, 1.3, 1.6, 2.2, 3.3,
|
||||
5.5, 8.3, 14, 25, 47, 91, 180, 360]
|
||||
|
||||
def initModule(self):
|
||||
self.io.setProperty('identification',
|
||||
[('\rSERIAL ECHO OFF;SH MODEL',
|
||||
'ILLEGAL WORD: MODEL')])
|
||||
super().initModule()
|
||||
|
||||
def _calculate_time(self, averexp, freq):
|
||||
self.calculated_time = self.calculate_time(averexp)
|
||||
|
||||
@Command(TupleOf(IntRange(0, 15)), result=FloatRange())
|
||||
def calculate_time(self, averexp):
|
||||
"""calculate estimated measuring time"""
|
||||
return self.MEAS_TIME_CONST[int(averexp)]
|
||||
|
||||
|
||||
class AH2700(AHBase):
|
||||
freq = Parameter(datatype=FloatRange(50, 20000, unit='Hz', fmtstr='%.1f'),
|
||||
readonly=False)
|
||||
freq_module = Property('''name of freq module
|
||||
|
||||
default: not created
|
||||
''',
|
||||
StringType(), default='')
|
||||
MEAS_PAT = r'F= *(?P<freq>[0-9.E+-]+) *HZ ' + AH2550.MEAS_PAT
|
||||
PATTERN = AH2550.PATTERN + [r'FREQUENCY *(?P<freq>[0-9.E+-]+)']
|
||||
COMMANDS = AH2550.COMMANDS + ['FR']
|
||||
PATTERN = [
|
||||
r'AVERAGE *AVEREXP=(?P<averexp>[0-9]*)',
|
||||
r'VOLTAGE HIGHEST *(?P<voltage>[0-9.E+-]+)',
|
||||
r'FREQUENCY *(?P<freq>[0-9.E+-]+)',
|
||||
]
|
||||
UNIT = 'DS'
|
||||
MEAS_PAT = (
|
||||
r'F= *(?P<freq>[0-9.E+-]+) *HZ '
|
||||
r'C= *(?P<cap>[0-9.E+-]+) *PF '
|
||||
r'L= *(?P<loss>[0-9.E+-]+) *(?P<lossunit>[A-Z]*) '
|
||||
f'V= *(?P<voltage>[0-9.E+-]+) *V *(?P<error>.*)$'
|
||||
)
|
||||
|
||||
def initModule(self):
|
||||
super().initModule()
|
||||
self.io.setProperty('identification',
|
||||
[('\r\nSERIAL ECHO OFF;SH MODEL',
|
||||
'MODEL/OPTIONS *AH2700')])
|
||||
|
||||
def scanModules(self):
|
||||
yield from super().scanModules()
|
||||
@@ -297,10 +391,39 @@ class AH2700(AH2550):
|
||||
'cap': self.name}
|
||||
|
||||
def write_freq(self, value):
|
||||
self._todo['freq'] = f'FR {value:g};SH FR'
|
||||
self.change('FR', f'{value:g}', 'freq')
|
||||
self.update_freq(value)
|
||||
return round(value, 1)
|
||||
|
||||
def update_meas(self, freq, **kwds):
|
||||
self.freq = float(freq)
|
||||
super().update_meas(**kwds)
|
||||
MEAS_TIME_CONST = [
|
||||
# (upper freq limit, meas time @ avrexp=7 - 0.8)
|
||||
(75, 20),
|
||||
(150, 10),
|
||||
(270, 5.62),
|
||||
(550, 2.34),
|
||||
(1100, 2.73),
|
||||
(4500, 1.02),
|
||||
(20000, 0.51),
|
||||
]
|
||||
|
||||
@Command(TupleOf(IntRange(0, 15), FloatRange(50, 20000)),
|
||||
result=FloatRange())
|
||||
def calculate_time(self, averexp, freq):
|
||||
"""calculate estimated measuring time
|
||||
|
||||
from time efficiency considerations averexp > 7 is recommended
|
||||
especially for freq < 550 no time may be saved with averexp <= 7
|
||||
"""
|
||||
for f, c in self.MEAS_TIME_CONST:
|
||||
if f > freq:
|
||||
const = c
|
||||
break
|
||||
else:
|
||||
const = self.MEAS_TIME_CONST[-1][1]
|
||||
if averexp >= 8:
|
||||
result = 0.8 + const * (0.5 + 2 ** (averexp - 8))
|
||||
elif freq < 550:
|
||||
result = 0.8 + const
|
||||
else:
|
||||
result = 0.6 + 2 ** (averexp - 7) * const
|
||||
return round(result, 1)
|
||||
|
||||
Reference in New Issue
Block a user