Compare commits
36 Commits
trinamic_p
...
uniax
Author | SHA1 | Date | |
---|---|---|---|
b30bd308a9 | |||
6c4bb78f97 | |||
b226f2c7c0 | |||
3687ed85e5 | |||
7ff88cf819 | |||
25b8780b11 | |||
246ab99e12 | |||
229604439b | |||
114af36ac6 | |||
ca6aebd290 | |||
49ad153605 | |||
c6157049d7 | |||
3977fad3f3 | |||
eaac83e4d5 | |||
1619e042e9 | |||
8d6ba91a5e | |||
21c49df1a2 | |||
a771259ecf | |||
c779d49548 | |||
5f65b6b4ce | |||
70c3f5f37f | |||
3e599a24d7 | |||
e638661edc | |||
772f45a241 | |||
e589ed1063 | |||
1a616ecab1 | |||
61aeafdfb6 | |||
c89c982c42 | |||
acbb17f367 | |||
4bda112bb7 | |||
8029443f1b | |||
57e9367e40 | |||
de7a91d727 | |||
078ac7c600 | |||
8b2c5f6144 | |||
99eb600d90 |
@ -1,35 +1,8 @@
|
|||||||
[node seatest.psi.ch]
|
[NODE]
|
||||||
description = SEA test
|
description = sea client (communication only)
|
||||||
|
id = comm.sea.psi.ch
|
||||||
|
|
||||||
[interface tcp]
|
[seaconn]
|
||||||
type = tcp
|
|
||||||
bindto = 0.0.0.0
|
|
||||||
bindport = 5002
|
|
||||||
|
|
||||||
[module seaconn]
|
|
||||||
class = secop_psi.sea.SeaClient
|
class = secop_psi.sea.SeaClient
|
||||||
description = a SEA connection
|
description = a SEA connection
|
||||||
uri = tcp://samenv.psi.ch:8645
|
visibility = 1
|
||||||
|
|
||||||
#[module t1]
|
|
||||||
#class = secop_psi.sea.SeaDrivable
|
|
||||||
#iodev = seaconn
|
|
||||||
#json_descr = tt.flamp.config
|
|
||||||
#remote_paths = . t1
|
|
||||||
|
|
||||||
#[module tw1]
|
|
||||||
#class = secop_psi.sea.SeaReadable
|
|
||||||
#iodev = seaconn
|
|
||||||
#json_descr = wall.lampovenwall.addon
|
|
||||||
#remote_paths = tw1
|
|
||||||
|
|
||||||
#[module pv]
|
|
||||||
#class = secop_psi.sea.SeaReadable
|
|
||||||
#iodev = seaconn
|
|
||||||
#json_descr = pv.flamp.config
|
|
||||||
|
|
||||||
#[module mf]
|
|
||||||
#class = secop.Proxy
|
|
||||||
#remote_class = secop_psi.ppms.Field
|
|
||||||
#description = magnetic field
|
|
||||||
#iodev = secnode
|
|
||||||
|
8
cfg/develop/seadesc.cfg
Normal file
8
cfg/develop/seadesc.cfg
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[NODE]
|
||||||
|
description = sea client (communication only)
|
||||||
|
id = comm.sea.psi.ch
|
||||||
|
|
||||||
|
[seaconn]
|
||||||
|
class = secop_psi.sea.SeaConfigCreator
|
||||||
|
description = a SEA connection. will shut down after getting the description
|
||||||
|
visibility = 1
|
17
cfg/ls240.cfg
Normal file
17
cfg/ls240.cfg
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[NODE]
|
||||||
|
id = ls240.psi.ch
|
||||||
|
description = ls240 test
|
||||||
|
|
||||||
|
[INTERFACE]
|
||||||
|
uri = tcp://5000
|
||||||
|
|
||||||
|
[T]
|
||||||
|
description = temperature on uniax stick
|
||||||
|
class = secop_psi.ls240.Ls240
|
||||||
|
iodev = T_iodev
|
||||||
|
|
||||||
|
[T_iodev]
|
||||||
|
class = secop.bytesio.BytesIO
|
||||||
|
description = IO device for LS240
|
||||||
|
uri = serial:///dev/ttyUSB0?baudrate=9600+parity=EVEN
|
||||||
|
timeout = 0.2
|
@ -1,11 +1,11 @@
|
|||||||
[NODE]
|
[NODE]
|
||||||
description = thin film oven for AMOR
|
description = thin film oven for AMOR
|
||||||
id = mbe.config.sea.psi.ch
|
id = fftf.config.sea.psi.ch
|
||||||
|
|
||||||
[sea_main]
|
[sea_main]
|
||||||
class = secop_psi.sea.SeaClient
|
class = secop_psi.sea.SeaClient
|
||||||
description = SEA connection to mbe
|
description = main sea connection for fftf.config
|
||||||
config = mbe.config
|
config = fftf.config
|
||||||
service = main
|
service = main
|
||||||
|
|
||||||
[tt]
|
[tt]
|
||||||
@ -13,23 +13,24 @@ class = secop_psi.sea.SeaDrivable
|
|||||||
iodev = sea_main
|
iodev = sea_main
|
||||||
sea_object = tt
|
sea_object = tt
|
||||||
|
|
||||||
[cc]
|
|
||||||
class = secop_psi.sea.SeaReadable
|
|
||||||
iodev = sea_main
|
|
||||||
sea_object = cc
|
|
||||||
|
|
||||||
[p]
|
[p]
|
||||||
class = secop_psi.sea.SeaReadable
|
class = secop_psi.sea.SeaReadable
|
||||||
iodev = sea_main
|
iodev = sea_main
|
||||||
sea_object = p
|
sea_object = p
|
||||||
extra_modules = vacuumpump, gasflow
|
extra_modules = vacuumpump gasflow tlimit tlimit_without_vacuum
|
||||||
|
|
||||||
[vacuumpump]
|
|
||||||
class = secop_psi.sea.SeaWritable
|
|
||||||
iodev = sea_main
|
|
||||||
single_module = p.vacuumpump
|
|
||||||
|
|
||||||
[gasflow]
|
[gasflow]
|
||||||
class = secop_psi.sea.SeaWritable
|
class = secop_psi.sea.SeaWritable
|
||||||
iodev = sea_main
|
iodev = sea_main
|
||||||
single_module = p.gasflow
|
single_module = p.gasflow
|
||||||
|
|
||||||
|
[vacuumpump]
|
||||||
|
class = secop_psi.sea.SeaWritable
|
||||||
|
iodev = sea_main
|
||||||
|
sea_object = p
|
||||||
|
rel_paths = vacuumpump tlimit tlimit_without_vacuum
|
||||||
|
|
||||||
|
[table]
|
||||||
|
class = secop_psi.sea.SeaModule
|
||||||
|
iodev = sea_main
|
||||||
|
sea_object = table
|
24
cfg/main/smamor.cfg
Normal file
24
cfg/main/smamor.cfg
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[NODE]
|
||||||
|
description = Keithley 2450 sourcemeter
|
||||||
|
id = smamor.config.sea.psi.ch
|
||||||
|
|
||||||
|
[sea_main]
|
||||||
|
class = secop_psi.sea.SeaClient
|
||||||
|
description = main sea connection for smamor.config
|
||||||
|
config = smamor.config
|
||||||
|
service = main
|
||||||
|
|
||||||
|
[smi]
|
||||||
|
class = secop_psi.sea.SeaDrivable
|
||||||
|
iodev = sea_main
|
||||||
|
sea_object = smi
|
||||||
|
|
||||||
|
[smv]
|
||||||
|
class = secop_psi.sea.SeaDrivable
|
||||||
|
iodev = sea_main
|
||||||
|
sea_object = smv
|
||||||
|
|
||||||
|
[r]
|
||||||
|
class = secop_psi.sea.SeaReadable
|
||||||
|
iodev = sea_main
|
||||||
|
sea_object = r
|
37
cfg/sea.cfg
37
cfg/sea.cfg
@ -1,35 +1,8 @@
|
|||||||
[node seatest.psi.ch]
|
[NODE]
|
||||||
description = SEA test
|
description = sea client (communication only)
|
||||||
|
id = comm.sea.psi.ch
|
||||||
|
|
||||||
[interface tcp]
|
[seaconn]
|
||||||
type = tcp
|
|
||||||
bindto = 0.0.0.0
|
|
||||||
bindport = 5002
|
|
||||||
|
|
||||||
[module seaconn]
|
|
||||||
class = secop_psi.sea.SeaClient
|
class = secop_psi.sea.SeaClient
|
||||||
description = a SEA connection
|
description = a SEA connection
|
||||||
uri = tcp://samenv.psi.ch:8645
|
visibility = 1
|
||||||
|
|
||||||
#[module t1]
|
|
||||||
#class = secop_psi.sea.SeaDrivable
|
|
||||||
#iodev = seaconn
|
|
||||||
#json_descr = tt.flamp.config
|
|
||||||
#remote_paths = . t1
|
|
||||||
|
|
||||||
#[module tw1]
|
|
||||||
#class = secop_psi.sea.SeaReadable
|
|
||||||
#iodev = seaconn
|
|
||||||
#json_descr = wall.lampovenwall.addon
|
|
||||||
#remote_paths = tw1
|
|
||||||
|
|
||||||
#[module pv]
|
|
||||||
#class = secop_psi.sea.SeaReadable
|
|
||||||
#iodev = seaconn
|
|
||||||
#json_descr = pv.flamp.config
|
|
||||||
|
|
||||||
#[module mf]
|
|
||||||
#class = secop.Proxy
|
|
||||||
#remote_class = secop_psi.ppms.Field
|
|
||||||
#description = magnetic field
|
|
||||||
#iodev = secnode
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{"tt": {"base": "/tt", "params": [{"path": "", "type": "float", "readonly": false, "cmd": "run tt", "description": "tt", "kids": 14},
|
{"tt": {"base": "/tt", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run tt", "description": "tt", "kids": 14},
|
||||||
{"path": "send", "type": "text", "readonly": false, "cmd": "tt send", "visibility": 3},
|
{"path": "send", "type": "text", "readonly": false, "cmd": "tt send", "visibility": 3},
|
||||||
{"path": "status", "type": "text", "visibility": 3},
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
{"path": "is_running", "type": "int", "readonly": false, "cmd": "tt is_running", "visibility": 3},
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "tt is_running", "visibility": 3},
|
||||||
@ -48,7 +49,10 @@
|
|||||||
{"path": "set/integ", "type": "float", "readonly": false, "cmd": "tt set/integ", "description": "bigger means faster"},
|
{"path": "set/integ", "type": "float", "readonly": false, "cmd": "tt set/integ", "description": "bigger means faster"},
|
||||||
{"path": "set/deriv", "type": "float", "readonly": false, "cmd": "tt set/deriv"},
|
{"path": "set/deriv", "type": "float", "readonly": false, "cmd": "tt set/deriv"},
|
||||||
{"path": "display", "type": "text", "readonly": false, "cmd": "tt display"},
|
{"path": "display", "type": "text", "readonly": false, "cmd": "tt display"},
|
||||||
{"path": "remote", "type": "bool"}]}, "cc": {"base": "/cc", "params": [{"path": "", "type": "bool", "kids": 96},
|
{"path": "remote", "type": "bool"}]},
|
||||||
|
|
||||||
|
"cc": {"base": "/cc", "params": [
|
||||||
|
{"path": "", "type": "bool", "kids": 96},
|
||||||
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
|
{"path": "send", "type": "text", "readonly": false, "cmd": "cc send", "visibility": 3},
|
||||||
{"path": "status", "type": "text", "visibility": 3},
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
|
{"path": "autodevice", "type": "bool", "readonly": false, "cmd": "cc autodevice"},
|
||||||
@ -144,10 +148,24 @@
|
|||||||
{"path": "tm", "type": "float", "visibility": 3},
|
{"path": "tm", "type": "float", "visibility": 3},
|
||||||
{"path": "tv", "type": "float", "visibility": 3},
|
{"path": "tv", "type": "float", "visibility": 3},
|
||||||
{"path": "tq", "type": "float", "visibility": 3},
|
{"path": "tq", "type": "float", "visibility": 3},
|
||||||
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]}, "p": {"base": "/p", "params": [{"path": "", "type": "float", "kids": 6},
|
{"path": "bdl", "type": "float", "readonly": false, "cmd": "cc bdl"}]},
|
||||||
|
|
||||||
|
"p": {"base": "/p", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 6},
|
||||||
{"path": "send", "type": "text", "readonly": false, "cmd": "p send", "visibility": 3},
|
{"path": "send", "type": "text", "readonly": false, "cmd": "p send", "visibility": 3},
|
||||||
{"path": "status", "type": "text", "visibility": 3},
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
{"path": "vacuumpump", "type": "bool", "readonly": false, "cmd": "p vacuumpump"},
|
{"path": "vacuumpump", "type": "bool", "readonly": false, "cmd": "p vacuumpump"},
|
||||||
{"path": "gasflow", "type": "bool", "readonly": false, "cmd": "p gasflow"},
|
{"path": "gasflow", "type": "bool", "readonly": false, "cmd": "p gasflow"},
|
||||||
{"path": "tlimit", "type": "float", "readonly": false, "cmd": "p tlimit"},
|
{"path": "tlimit", "type": "float", "readonly": false, "cmd": "p tlimit"},
|
||||||
{"path": "tlimit_without_vacuum", "type": "float", "readonly": false, "cmd": "p tlimit_without_vacuum"}]}}
|
{"path": "tlimit_without_vacuum", "type": "float", "readonly": false, "cmd": "p tlimit_without_vacuum"}]},
|
||||||
|
|
||||||
|
"table": {"base": "/table", "params": [
|
||||||
|
{"path": "", "type": "none", "kids": 8},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "table send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "fix_tt_set_prop", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_prop"},
|
||||||
|
{"path": "val_tt_set_prop", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_prop", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_prop", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."},
|
||||||
|
{"path": "fix_tt_set_integ", "type": "bool", "readonly": false, "cmd": "table fix_tt_set_integ"},
|
||||||
|
{"path": "val_tt_set_integ", "type": "float"},
|
||||||
|
{"path": "tbl_tt_set_integ", "type": "text", "readonly": false, "cmd": "table tbl_tt_set_integ", "description": "enter value pair separated with colon T1:par1 T2:par2 ..."}]}}
|
36
cfg/sea/smamor.config.json
Normal file
36
cfg/sea/smamor.config.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{"smi": {"base": "/smi", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run smi", "kids": 13},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "smi send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "smi is_running", "visibility": 3},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "output", "type": "bool", "readonly": false, "cmd": "smi output"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "smi set"},
|
||||||
|
{"path": "limited", "type": "float"},
|
||||||
|
{"path": "limit", "type": "float", "readonly": false, "cmd": "smi limit"},
|
||||||
|
{"path": "lastmsg", "type": "text"},
|
||||||
|
{"path": "script", "type": "text", "readonly": false, "cmd": "smi script", "description": "scriptfile containing 'while' and 'halt' scripts"},
|
||||||
|
{"path": "delay", "type": "float", "readonly": false, "cmd": "smi delay"},
|
||||||
|
{"path": "step", "type": "float", "readonly": false, "cmd": "smi step"},
|
||||||
|
{"path": "codeversion", "type": "text", "visibility": 3}]},
|
||||||
|
|
||||||
|
"smv": {"base": "/smv", "params": [
|
||||||
|
{"path": "", "type": "float", "readonly": false, "cmd": "run smv", "kids": 13},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "smv send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3},
|
||||||
|
{"path": "is_running", "type": "int", "readonly": false, "cmd": "smv is_running", "visibility": 3},
|
||||||
|
{"path": "target", "type": "float"},
|
||||||
|
{"path": "output", "type": "bool", "readonly": false, "cmd": "smv output"},
|
||||||
|
{"path": "set", "type": "float", "readonly": false, "cmd": "smv set"},
|
||||||
|
{"path": "limited", "type": "float"},
|
||||||
|
{"path": "limit", "type": "float", "readonly": false, "cmd": "smv limit"},
|
||||||
|
{"path": "lastmsg", "type": "text"},
|
||||||
|
{"path": "script", "type": "text", "readonly": false, "cmd": "smv script", "description": "scriptfile containing 'while' and 'halt' scripts"},
|
||||||
|
{"path": "delay", "type": "float", "readonly": false, "cmd": "smv delay"},
|
||||||
|
{"path": "step", "type": "float", "readonly": false, "cmd": "smv step"},
|
||||||
|
{"path": "codeversion", "type": "text", "visibility": 3}]},
|
||||||
|
|
||||||
|
"r": {"base": "/r", "params": [
|
||||||
|
{"path": "", "type": "float", "kids": 2},
|
||||||
|
{"path": "send", "type": "text", "readonly": false, "cmd": "r send", "visibility": 3},
|
||||||
|
{"path": "status", "type": "text", "visibility": 3}]}}
|
@ -23,4 +23,3 @@ speed=40
|
|||||||
encoder_tolerance=3.6
|
encoder_tolerance=3.6
|
||||||
free_wheeling=0.1
|
free_wheeling=0.1
|
||||||
power_down_delay=0.1
|
power_down_delay=0.1
|
||||||
# pull_up=1
|
|
||||||
|
@ -8,25 +8,39 @@ uri = tcp://5000
|
|||||||
[drv_iodev]
|
[drv_iodev]
|
||||||
description =
|
description =
|
||||||
class = secop.bytesio.BytesIO
|
class = secop.bytesio.BytesIO
|
||||||
uri = serial:///dev/ttyUSB0?baudrate=57600
|
# uri = serial:///dev/ttyUSB1?baudrate=57600
|
||||||
# uri = serial:///dev/ttyUSB0?baudrate=9600
|
uri = tcp://192.168.127.254:3002
|
||||||
|
|
||||||
[drv]
|
[drv]
|
||||||
description = trinamic motor test
|
description = trinamic motor test
|
||||||
class = secop_psi.trinamic.Motor
|
class = secop_psi.trinamic.Motor
|
||||||
iodev = drv_iodev
|
iodev = drv_iodev
|
||||||
standby_current=0.1
|
standby_current=0.1
|
||||||
maxcurrent=1.4
|
maxcurrent=0.2
|
||||||
acceleration=50
|
acceleration=150.
|
||||||
maxspeed=200
|
movelimit=360
|
||||||
zero=-36
|
speed=40
|
||||||
enc_tolerance=3.6
|
encoder_tolerance=3.6
|
||||||
free_wheeling=0.001
|
free_wheeling=0.1
|
||||||
pull_up=1
|
power_down_delay=0.1
|
||||||
|
|
||||||
[force]
|
[force]
|
||||||
description = DPM driver to read out the transducer value, write and read the offset and scale factor
|
description = DPM driver to read out the transducer value, write and read the offset and scale factor
|
||||||
class = secop_psi.dpm.DPM3
|
class = secop_psi.dpm.DPM3
|
||||||
uri = serial:///dev/ttyUSB1?baudrate=9600
|
#uri = serial:///dev/ttyUSB0?baudrate=9600
|
||||||
|
uri = tcp://192.168.127.254:3001
|
||||||
digits = 2
|
digits = 2
|
||||||
scale_factor = 0.0156
|
scale_factor = 0.0156
|
||||||
|
motor = drv
|
||||||
|
|
||||||
|
[res]
|
||||||
|
description = temperature on uniax stick
|
||||||
|
class = secop_psi.ls340res.ResChannel
|
||||||
|
uri = tcp://192.168.127.254:3003
|
||||||
|
channel = C
|
||||||
|
|
||||||
|
[T]
|
||||||
|
class = secop_psi.softcal.Sensor
|
||||||
|
rawsensor = res
|
||||||
|
calib = /home/l_samenv/frappy/secop_psi/calcurves/X132254.340
|
||||||
|
value.unit = K
|
||||||
|
@ -37,4 +37,5 @@ from secop.poller import AUTO, DYNAMIC, REGULAR, SLOW
|
|||||||
from secop.properties import Property
|
from secop.properties import Property
|
||||||
from secop.proxy import Proxy, SecNode, proxy_class
|
from secop.proxy import Proxy, SecNode, proxy_class
|
||||||
from secop.stringio import HasIodev, StringIO
|
from secop.stringio import HasIodev, StringIO
|
||||||
|
from secop.bytesio import BytesIO
|
||||||
from secop.persistent import PersistentMixin, PersistentParam
|
from secop.persistent import PersistentMixin, PersistentParam
|
||||||
|
@ -165,7 +165,8 @@ class ModuleCtrl(QWidget):
|
|||||||
result = None
|
result = None
|
||||||
qualifiers = {}
|
qualifiers = {}
|
||||||
# XXX: flag missing data report as error
|
# XXX: flag missing data report as error
|
||||||
showCommandResultDialog(command, args, result, qualifiers)
|
if result is not None:
|
||||||
|
showCommandResultDialog(command, args, result, qualifiers)
|
||||||
|
|
||||||
def _initModuleWidgets(self):
|
def _initModuleWidgets(self):
|
||||||
initValues = self._node.queryCache(self._module)
|
initValues = self._node.queryCache(self._module)
|
||||||
|
@ -76,7 +76,13 @@ class GenericParameterWidget(ParameterWidget):
|
|||||||
self.setLineEdit.text())
|
self.setLineEdit.text())
|
||||||
|
|
||||||
def updateValue(self, value):
|
def updateValue(self, value):
|
||||||
self.currentLineEdit.setText(str(value))
|
fmtstr = getattr(self._datatype, 'fmtstr', '%s')
|
||||||
|
if value.readerror:
|
||||||
|
value = str(value)
|
||||||
|
else:
|
||||||
|
value = fmtstr % (value.value,)
|
||||||
|
self.currentLineEdit.setText(value)
|
||||||
|
# self.currentLineEdit.setText(str(value))
|
||||||
|
|
||||||
|
|
||||||
class EnumParameterWidget(GenericParameterWidget):
|
class EnumParameterWidget(GenericParameterWidget):
|
||||||
|
@ -251,7 +251,9 @@ class AsynSerial(AsynConn):
|
|||||||
if not fullname.startswith(name):
|
if not fullname.startswith(name):
|
||||||
raise ConfigError('illegal parity: %s' % parity)
|
raise ConfigError('illegal parity: %s' % parity)
|
||||||
options['parity'] = name[0]
|
options['parity'] = name[0]
|
||||||
if 'timeout' not in options:
|
if 'timeout' in options:
|
||||||
|
options['timeout'] = float(self.timeout)
|
||||||
|
else:
|
||||||
options['timeout'] = self.timeout
|
options['timeout'] = self.timeout
|
||||||
try:
|
try:
|
||||||
self.connection = Serial(dev, **options)
|
self.connection = Serial(dev, **options)
|
||||||
|
@ -92,7 +92,7 @@ class PersistentMixin(HasAccessibles):
|
|||||||
try:
|
try:
|
||||||
with open(self.persistentFile, 'r') as f:
|
with open(self.persistentFile, 'r') as f:
|
||||||
self.persistentData = json.load(f)
|
self.persistentData = json.load(f)
|
||||||
except FileNotFoundError:
|
except Exception:
|
||||||
self.persistentData = {}
|
self.persistentData = {}
|
||||||
writeDict = {}
|
writeDict = {}
|
||||||
for pname in self.parameters:
|
for pname in self.parameters:
|
||||||
|
208
secop_psi/calcurves/X132254.340
Normal file
208
secop_psi/calcurves/X132254.340
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
Sensor Model: CX-1050-SD 2018-11-20
|
||||||
|
Serial Number: X132254
|
||||||
|
Data Format: 4 (Log Ohms/Kelvin)
|
||||||
|
SetPoint Limit: 330.0 (Kelvin)
|
||||||
|
Temperature coefficient: 1 (Negative)
|
||||||
|
Number of Breakpoints: 199
|
||||||
|
|
||||||
|
No. Units Temperature (K)
|
||||||
|
|
||||||
|
1 1.865581 330.0000
|
||||||
|
2 1.889780 310.0000
|
||||||
|
3 1.900613 301.5330
|
||||||
|
4 1.911510 293.2973
|
||||||
|
5 1.922466 285.2865
|
||||||
|
6 1.933476 277.4945
|
||||||
|
7 1.944536 269.9153
|
||||||
|
8 1.955638 262.5431
|
||||||
|
9 1.966779 255.3723
|
||||||
|
10 1.977950 248.3974
|
||||||
|
11 1.989148 241.6129
|
||||||
|
12 2.000369 235.0138
|
||||||
|
13 2.011610 228.5949
|
||||||
|
14 2.022870 222.3513
|
||||||
|
15 2.034145 216.2782
|
||||||
|
16 2.045433 210.3710
|
||||||
|
17 2.056730 204.6252
|
||||||
|
18 2.068035 199.0363
|
||||||
|
19 2.079343 193.6000
|
||||||
|
20 2.090652 188.3123
|
||||||
|
21 2.101960 183.1689
|
||||||
|
22 2.113263 178.1660
|
||||||
|
23 2.124559 173.2998
|
||||||
|
24 2.135845 168.5665
|
||||||
|
25 2.147117 163.9624
|
||||||
|
26 2.158374 159.4842
|
||||||
|
27 2.169612 155.1282
|
||||||
|
28 2.180830 150.8912
|
||||||
|
29 2.192023 146.7699
|
||||||
|
30 2.203192 142.7612
|
||||||
|
31 2.214333 138.8620
|
||||||
|
32 2.225444 135.0693
|
||||||
|
33 2.236525 131.3801
|
||||||
|
34 2.247573 127.7918
|
||||||
|
35 2.258586 124.3014
|
||||||
|
36 2.269564 120.9064
|
||||||
|
37 2.280509 117.6041
|
||||||
|
38 2.291423 114.3920
|
||||||
|
39 2.302308 111.2676
|
||||||
|
40 2.313167 108.2285
|
||||||
|
41 2.324003 105.2725
|
||||||
|
42 2.334817 102.3972
|
||||||
|
43 2.345609 99.60045
|
||||||
|
44 2.356380 96.88007
|
||||||
|
45 2.367129 94.23400
|
||||||
|
46 2.377857 91.66019
|
||||||
|
47 2.388562 89.15669
|
||||||
|
48 2.399245 86.72156
|
||||||
|
49 2.409907 84.35294
|
||||||
|
50 2.420547 82.04902
|
||||||
|
51 2.431166 79.80803
|
||||||
|
52 2.441762 77.62824
|
||||||
|
53 2.452338 75.50799
|
||||||
|
54 2.462894 73.44565
|
||||||
|
55 2.473431 71.43963
|
||||||
|
56 2.483949 69.48841
|
||||||
|
57 2.494449 67.59048
|
||||||
|
58 2.504932 65.74439
|
||||||
|
59 2.515397 63.94872
|
||||||
|
60 2.525846 62.20210
|
||||||
|
61 2.536278 60.50318
|
||||||
|
62 2.546695 58.85066
|
||||||
|
63 2.557096 57.24328
|
||||||
|
64 2.567482 55.67980
|
||||||
|
65 2.577854 54.15902
|
||||||
|
66 2.588212 52.67978
|
||||||
|
67 2.598555 51.24095
|
||||||
|
68 2.608882 49.84141
|
||||||
|
69 2.619195 48.48010
|
||||||
|
70 2.629492 47.15596
|
||||||
|
71 2.639773 45.86800
|
||||||
|
72 2.650037 44.61521
|
||||||
|
73 2.660285 43.39664
|
||||||
|
74 2.670517 42.21135
|
||||||
|
75 2.680731 41.05844
|
||||||
|
76 2.690928 39.93701
|
||||||
|
77 2.701107 38.84622
|
||||||
|
78 2.711268 37.78522
|
||||||
|
79 2.721411 36.75319
|
||||||
|
80 2.731536 35.74936
|
||||||
|
81 2.741644 34.77294
|
||||||
|
82 2.751735 33.82319
|
||||||
|
83 2.761808 32.89938
|
||||||
|
84 2.771865 32.00080
|
||||||
|
85 2.781907 31.12677
|
||||||
|
86 2.791933 30.27661
|
||||||
|
87 2.801945 29.44966
|
||||||
|
88 2.811944 28.64531
|
||||||
|
89 2.821930 27.86292
|
||||||
|
90 2.831903 27.10191
|
||||||
|
91 2.841865 26.36167
|
||||||
|
92 2.851817 25.64166
|
||||||
|
93 2.861758 24.94131
|
||||||
|
94 2.871690 24.26009
|
||||||
|
95 2.881614 23.59748
|
||||||
|
96 2.891532 22.95297
|
||||||
|
97 2.901446 22.32605
|
||||||
|
98 2.911361 21.71626
|
||||||
|
99 2.921277 21.12313
|
||||||
|
100 2.931198 20.54620
|
||||||
|
101 2.941127 19.98502
|
||||||
|
102 2.951066 19.43917
|
||||||
|
103 2.961018 18.90823
|
||||||
|
104 2.970985 18.39179
|
||||||
|
105 2.980970 17.88946
|
||||||
|
106 2.990974 17.40085
|
||||||
|
107 3.001002 16.92558
|
||||||
|
108 3.011054 16.46329
|
||||||
|
109 3.021133 16.01363
|
||||||
|
110 3.031243 15.57626
|
||||||
|
111 3.041384 15.15082
|
||||||
|
112 3.051561 14.73701
|
||||||
|
113 3.061776 14.33450
|
||||||
|
114 3.072032 13.94298
|
||||||
|
115 3.082331 13.56216
|
||||||
|
116 3.092677 13.19174
|
||||||
|
117 3.103073 12.83143
|
||||||
|
118 3.113522 12.48097
|
||||||
|
119 3.124027 12.14008
|
||||||
|
120 3.134592 11.80850
|
||||||
|
121 3.145221 11.48597
|
||||||
|
122 3.155918 11.17226
|
||||||
|
123 3.166687 10.86711
|
||||||
|
124 3.177532 10.57030
|
||||||
|
125 3.188458 10.28159
|
||||||
|
126 3.199469 10.00077
|
||||||
|
127 3.210570 9.727624
|
||||||
|
128 3.221764 9.461935
|
||||||
|
129 3.233053 9.203502
|
||||||
|
130 3.244440 8.952128
|
||||||
|
131 3.255927 8.707619
|
||||||
|
132 3.267518 8.469789
|
||||||
|
133 3.279216 8.238455
|
||||||
|
134 3.291024 8.013439
|
||||||
|
135 3.302945 7.794568
|
||||||
|
136 3.314984 7.581676
|
||||||
|
137 3.327143 7.374599
|
||||||
|
138 3.339428 7.173177
|
||||||
|
139 3.351843 6.977257
|
||||||
|
140 3.364390 6.786688
|
||||||
|
141 3.377076 6.601324
|
||||||
|
142 3.389904 6.421023
|
||||||
|
143 3.402879 6.245646
|
||||||
|
144 3.416005 6.075059
|
||||||
|
145 3.429288 5.909132
|
||||||
|
146 3.442733 5.747736
|
||||||
|
147 3.456347 5.590749
|
||||||
|
148 3.470134 5.438050
|
||||||
|
149 3.484101 5.289521
|
||||||
|
150 3.498250 5.145049
|
||||||
|
151 3.512586 5.004522
|
||||||
|
152 3.527113 4.867834
|
||||||
|
153 3.541835 4.734880
|
||||||
|
154 3.556757 4.605557
|
||||||
|
155 3.571882 4.479766
|
||||||
|
156 3.587215 4.357410
|
||||||
|
157 3.602759 4.238397
|
||||||
|
158 3.618520 4.122634
|
||||||
|
159 3.634504 4.010033
|
||||||
|
160 3.650715 3.900507
|
||||||
|
161 3.667161 3.793973
|
||||||
|
162 3.683849 3.690349
|
||||||
|
163 3.700786 3.589555
|
||||||
|
164 3.717980 3.491514
|
||||||
|
165 3.735437 3.396150
|
||||||
|
166 3.753166 3.303392
|
||||||
|
167 3.771176 3.213166
|
||||||
|
168 3.789476 3.125406
|
||||||
|
169 3.808071 3.040042
|
||||||
|
170 3.826971 2.957009
|
||||||
|
171 3.846182 2.876245
|
||||||
|
172 3.865712 2.797686
|
||||||
|
173 3.885567 2.721273
|
||||||
|
174 3.905755 2.646948
|
||||||
|
175 3.926284 2.574652
|
||||||
|
176 3.947160 2.504331
|
||||||
|
177 3.968390 2.435930
|
||||||
|
178 3.989980 2.369398
|
||||||
|
179 4.011939 2.304683
|
||||||
|
180 4.034269 2.241735
|
||||||
|
181 4.056978 2.180507
|
||||||
|
182 4.080072 2.120951
|
||||||
|
183 4.103563 2.063022
|
||||||
|
184 4.127465 2.006675
|
||||||
|
185 4.151790 1.951866
|
||||||
|
186 4.176551 1.898555
|
||||||
|
187 4.201764 1.846700
|
||||||
|
188 4.227442 1.796262
|
||||||
|
189 4.253600 1.747201
|
||||||
|
190 4.280254 1.699479
|
||||||
|
191 4.307419 1.653062
|
||||||
|
192 4.335111 1.607912
|
||||||
|
193 4.363347 1.563995
|
||||||
|
194 4.392142 1.521278
|
||||||
|
195 4.421513 1.479727
|
||||||
|
196 4.451476 1.439312
|
||||||
|
197 4.482048 1.400000
|
||||||
|
198 4.664046 1.200000
|
||||||
|
199 4.907708 1.000000
|
@ -16,11 +16,13 @@
|
|||||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
# Module authors:
|
# Module authors:
|
||||||
# ...
|
# M. Zolliker <markus.zolliker@psi.ch>
|
||||||
#
|
#
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
|
"""transducer DPM3 read out"""
|
||||||
|
|
||||||
from secop.core import Readable, Parameter, FloatRange, BoolType, StringIO, HasIodev, IntRange, Done
|
from secop.core import Drivable, Parameter, FloatRange, BoolType, StringIO,\
|
||||||
|
HasIodev, IntRange, Done, Attached, Command
|
||||||
|
|
||||||
|
|
||||||
class DPM3IO(StringIO):
|
class DPM3IO(StringIO):
|
||||||
@ -43,7 +45,7 @@ def float2hex(value, digits):
|
|||||||
return '%06X' % intvalue
|
return '%06X' % intvalue
|
||||||
|
|
||||||
|
|
||||||
class DPM3(HasIodev, Readable):
|
class DPM3(HasIodev, Drivable):
|
||||||
OFFSET = 0x8f
|
OFFSET = 0x8f
|
||||||
SCALE = 0x8c
|
SCALE = 0x8c
|
||||||
|
|
||||||
@ -52,8 +54,11 @@ class DPM3(HasIodev, Readable):
|
|||||||
|
|
||||||
iodevClass = DPM3IO
|
iodevClass = DPM3IO
|
||||||
|
|
||||||
|
motor = Attached()
|
||||||
digits = Parameter('number of digits for value', IntRange(0, 5), initwrite=True, readonly=False)
|
digits = Parameter('number of digits for value', IntRange(0, 5), initwrite=True, readonly=False)
|
||||||
value = Parameter(unit='N')
|
value = Parameter(unit='N')
|
||||||
|
target = Parameter(unit='N')
|
||||||
|
step = Parameter('maximum motor step', FloatRange(unit='deg'), default=5, readonly=False)
|
||||||
|
|
||||||
offset = Parameter('', FloatRange(-1e5, 1e5), readonly=False, poll=True)
|
offset = Parameter('', FloatRange(-1e5, 1e5), readonly=False, poll=True)
|
||||||
|
|
||||||
@ -62,6 +67,8 @@ class DPM3(HasIodev, Readable):
|
|||||||
thus a maximl output of 1500. 10=150/f
|
thus a maximl output of 1500. 10=150/f
|
||||||
"""
|
"""
|
||||||
scale_factor = Parameter('', FloatRange(-1e5, 1e5, unit='input_units/N'), readonly=False, poll=True)
|
scale_factor = Parameter('', FloatRange(-1e5, 1e5, unit='input_units/N'), readonly=False, poll=True)
|
||||||
|
_target = None
|
||||||
|
fast_pollfactor = 0.01
|
||||||
|
|
||||||
def query(self, adr, value=None):
|
def query(self, adr, value=None):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
@ -93,7 +100,7 @@ class DPM3(HasIodev, Readable):
|
|||||||
return value/mag
|
return value/mag
|
||||||
else:
|
else:
|
||||||
return hex2float(hexvalue, self.digits)
|
return hex2float(hexvalue, self.digits)
|
||||||
|
|
||||||
def write_digits(self, value):
|
def write_digits(self, value):
|
||||||
# value defines the number of digits
|
# value defines the number of digits
|
||||||
back_value=self._iodev.communicate('*1F135%02X\r*1G135' % (value + 1))
|
back_value=self._iodev.communicate('*1F135%02X\r*1G135' % (value + 1))
|
||||||
@ -108,9 +115,37 @@ class DPM3(HasIodev, Readable):
|
|||||||
return int(back_value,16) - 1
|
return int(back_value,16) - 1
|
||||||
|
|
||||||
def read_value(self):
|
def read_value(self):
|
||||||
value = self._iodev.communicate('*1B1')
|
value = float(self._iodev.communicate('*1B1'))
|
||||||
return float(value)
|
if self._target is not None:
|
||||||
|
mot = self._motor
|
||||||
|
if self._direction * (self._target - value) > 0:
|
||||||
|
if not mot.isBusy():
|
||||||
|
step = self.step * self._direction
|
||||||
|
mot.write_target(mot.value + step)
|
||||||
|
else:
|
||||||
|
print(value)
|
||||||
|
self.stop()
|
||||||
|
self.status = self.Status.IDLE, 'target reached'
|
||||||
|
return value
|
||||||
|
|
||||||
|
def write_target(self, target):
|
||||||
|
self._target = target
|
||||||
|
if target - self.value > 0:
|
||||||
|
self._direction = 1
|
||||||
|
else:
|
||||||
|
self._direction = -1
|
||||||
|
print('direction', self._direction)
|
||||||
|
self.status = self.Status.BUSY, 'moving motor'
|
||||||
|
if self._motor.status[0] == self.Status.ERROR:
|
||||||
|
self._motor.reset()
|
||||||
|
return target
|
||||||
|
|
||||||
|
@Command()
|
||||||
|
def stop(self):
|
||||||
|
self._target = None
|
||||||
|
self._motor.stop()
|
||||||
|
self.status = self.Status.IDLE, 'stopped'
|
||||||
|
|
||||||
def read_offset(self):
|
def read_offset(self):
|
||||||
reply = self.query(self.OFFSET)
|
reply = self.query(self.OFFSET)
|
||||||
return reply
|
return reply
|
||||||
|
102
secop_psi/ls240.py
Normal file
102
secop_psi/ls240.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# *****************************************************************************
|
||||||
|
# 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>
|
||||||
|
# *****************************************************************************
|
||||||
|
"""LakeShore 240 temperature monitor"""
|
||||||
|
|
||||||
|
import struct
|
||||||
|
from secop.core import FloatRange, HasIodev, Readable, Parameter, BytesIO
|
||||||
|
from secop.errors import CommunicationFailedError
|
||||||
|
|
||||||
|
SD1= 0x10
|
||||||
|
SD2= 0x68
|
||||||
|
FC = 0x49
|
||||||
|
ED = 0x16
|
||||||
|
|
||||||
|
STATUS_REQ = 0x49
|
||||||
|
|
||||||
|
def dehex(msg):
|
||||||
|
return bytes(int(b, 16) for b in msg.split())
|
||||||
|
|
||||||
|
def hexify(msg):
|
||||||
|
return ' '.join('%2.2X' % b for b in msg)
|
||||||
|
|
||||||
|
|
||||||
|
class Ls240(HasIodev, Readable):
|
||||||
|
value = Parameter('sensor reading', FloatRange(unit='Ohm'))
|
||||||
|
|
||||||
|
iodevClass = BytesIO
|
||||||
|
|
||||||
|
def request(self, replylen, data='', ext=None, dst_adr=3, src_adr=2):
|
||||||
|
data = dehex(data)
|
||||||
|
if ext is None:
|
||||||
|
ext = len(data) > 1
|
||||||
|
if ext:
|
||||||
|
dst_adr |= 0x80
|
||||||
|
src_adr |= 0x80
|
||||||
|
if len(data) > 1:
|
||||||
|
length = len(data) + 2
|
||||||
|
hdr = [SD2, length, length, SD2]
|
||||||
|
else:
|
||||||
|
hdr = [SD1]
|
||||||
|
mid = [dst_adr, src_adr] + list(data)
|
||||||
|
checksum = sum(mid) % 256
|
||||||
|
msg = bytes(hdr + mid + [checksum, ED])
|
||||||
|
for i in range(10):
|
||||||
|
try:
|
||||||
|
# print('>', hexify(msg))
|
||||||
|
reply = self._iodev.communicate(msg, replylen)
|
||||||
|
# print('<', hexify(reply))
|
||||||
|
except (TimeoutError, CommunicationFailedError):
|
||||||
|
continue
|
||||||
|
return reply
|
||||||
|
return None
|
||||||
|
|
||||||
|
def read_value(self):
|
||||||
|
|
||||||
|
# check connection
|
||||||
|
self.request(6, '49')
|
||||||
|
|
||||||
|
# get diag
|
||||||
|
# 3C: slave diag, (what means 3E?)
|
||||||
|
reply = self.request(17, '6D 3C 3E')
|
||||||
|
assert reply[13:15] == b'\x0f\x84' # LS240 ident
|
||||||
|
|
||||||
|
# set parameters
|
||||||
|
# 3D set param (what means 3E?)
|
||||||
|
# B0 FF FF: no watchdog, 00: min wait, 0F 84: ident, 01: group
|
||||||
|
assert b'\xe5' == self.request(1, '5D 3D 3E B0 FF FF 00 0F 84 01')
|
||||||
|
|
||||||
|
# set config
|
||||||
|
# 3E set config (what means 2nd 3E?)
|
||||||
|
# 93: input only, 4 == 3+1 bytes
|
||||||
|
assert b'\xe5' == self.request(1, '7D 3E 3E 93')
|
||||||
|
|
||||||
|
# get diag
|
||||||
|
# 3C: slave diag, (what means 3E?)
|
||||||
|
reply = self.request(17, '5D 3C 3E')
|
||||||
|
assert reply[13:15] == b'\x0f\x84' # LS240 ident
|
||||||
|
|
||||||
|
# get data
|
||||||
|
# do not know what 42 24 means
|
||||||
|
reply = self.request(13, '7D 42 24', ext=0)
|
||||||
|
print('DATA', reply)
|
||||||
|
value = struct.unpack('>f', reply[7:11])[0]
|
||||||
|
print('VALUE', value)
|
||||||
|
return value
|
45
secop_psi/ls340res.py
Normal file
45
secop_psi/ls340res.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# *****************************************************************************
|
||||||
|
# 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>
|
||||||
|
# *****************************************************************************
|
||||||
|
"""very simple LakeShore Model 340 driver, resistivity only"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from secop.datatypes import StringType, FloatRange
|
||||||
|
from secop.modules import Parameter, Property, Readable
|
||||||
|
from secop.stringio import HasIodev, StringIO
|
||||||
|
|
||||||
|
|
||||||
|
class LscIO(StringIO):
|
||||||
|
identification = [('*IDN?', 'LSCI,MODEL340,.*')]
|
||||||
|
end_of_line = '\r'
|
||||||
|
wait_before = 0.05
|
||||||
|
|
||||||
|
|
||||||
|
class ResChannel(HasIodev, Readable):
|
||||||
|
"""temperature channel on Lakeshore 340"""
|
||||||
|
|
||||||
|
iodevClass = LscIO
|
||||||
|
|
||||||
|
value = Parameter(datatype=FloatRange(unit='Ohm'))
|
||||||
|
channel = Property('the channel A,B,C or D', StringType())
|
||||||
|
|
||||||
|
def read_value(self):
|
||||||
|
return self._iodev.communicate('SRDG?%s' % self.channel)
|
@ -28,12 +28,12 @@ class Ls370Sim(Communicator):
|
|||||||
('RDGR?%d', '1.0'),
|
('RDGR?%d', '1.0'),
|
||||||
('RDGST?%d', '0'),
|
('RDGST?%d', '0'),
|
||||||
('RDGRNG?%d', '0,5,5,0,0'),
|
('RDGRNG?%d', '0,5,5,0,0'),
|
||||||
('INSET?%d', '1,5,5,0,0'),
|
('INSET?%d', '1,3,3,0,0'),
|
||||||
('FILTER?%d', '1,5,80'),
|
('FILTER?%d', '1,1,80'),
|
||||||
]
|
]
|
||||||
OTHER_COMMANDS = [
|
OTHER_COMMANDS = [
|
||||||
('*IDN?', 'LSCI,MODEL370,370184,05302003'),
|
('*IDN?', 'LSCI,MODEL370,370184,05302003'),
|
||||||
('SCAN?', '3,1'),
|
('SCAN?', '3,0'),
|
||||||
]
|
]
|
||||||
|
|
||||||
def earlyInit(self):
|
def earlyInit(self):
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -79,7 +78,7 @@ for confdir in getGeneralConfig()['confdir'].split(os.pathsep):
|
|||||||
if exists(seaconfdir):
|
if exists(seaconfdir):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
seaconfdir = None
|
seaconfdir = os.environ.get('FRAPPY_SEA_DIR')
|
||||||
|
|
||||||
|
|
||||||
def get_sea_port(instance):
|
def get_sea_port(instance):
|
||||||
@ -263,18 +262,37 @@ class SeaClient(ProxyClient, Module):
|
|||||||
if value is None:
|
if value is None:
|
||||||
value = oldv
|
value = oldv
|
||||||
if value != oldv or str(readerror) != str(oldr) or abs(now - oldt) > 60:
|
if value != oldv or str(readerror) != str(oldr) or abs(now - oldt) > 60:
|
||||||
# do not update unchanged values within 0.1 sec
|
# do not update unchanged values within 60 sec
|
||||||
self.updateValue(module, param, value, now, readerror)
|
self.updateValue(module, param, value, now, readerror)
|
||||||
|
|
||||||
|
|
||||||
@Command(StringType(), result=StringType())
|
@Command(StringType(), result=StringType())
|
||||||
def communicate(self, command):
|
def communicate(self, command):
|
||||||
"""send a command to SEA"""
|
"""send a command to SEA"""
|
||||||
reply = self.request(command)
|
reply = self.request(command)
|
||||||
return reply
|
return reply
|
||||||
|
|
||||||
@Command(result=StringType())
|
@Command(StringType(), result=StringType())
|
||||||
def describe(self):
|
def query(self, cmd):
|
||||||
"""save objects (and sub-objects) description"""
|
"""a request checking for errors and accepting 0 or 1 line as result"""
|
||||||
|
errors = []
|
||||||
|
reply = None
|
||||||
|
for line in self.request(cmd).split('\n'):
|
||||||
|
if line.strip().startswith('ERROR:'):
|
||||||
|
errors.append(line[6:].strip())
|
||||||
|
elif reply is None:
|
||||||
|
reply = line.strip()
|
||||||
|
else:
|
||||||
|
self.log.info('SEA: superfluous reply %r to %r', reply, cmd)
|
||||||
|
if errors:
|
||||||
|
raise HardwareError('; '.join(errors))
|
||||||
|
return reply
|
||||||
|
|
||||||
|
|
||||||
|
class SeaConfigCreator(SeaClient):
|
||||||
|
def startModule(self, started_callback):
|
||||||
|
"""save objects (and sub-objects) description and exit"""
|
||||||
|
self._connect(lambda: None)
|
||||||
reply = self.request('describe_all')
|
reply = self.request('describe_all')
|
||||||
reply = ''.join('' if line.startswith('WARNING') else line for line in reply.split('\n'))
|
reply = ''.join('' if line.startswith('WARNING') else line for line in reply.split('\n'))
|
||||||
description, reply = json.loads(reply)
|
description, reply = json.loads(reply)
|
||||||
@ -301,11 +319,11 @@ class SeaClient(ProxyClient, Module):
|
|||||||
nodedescr=description.get(filename, filename)))
|
nodedescr=description.get(filename, filename)))
|
||||||
for obj in descr:
|
for obj in descr:
|
||||||
fp.write(CFG_MODULE % dict(modcls=modcls[obj], module=obj, seaconn=seaconn))
|
fp.write(CFG_MODULE % dict(modcls=modcls[obj], module=obj, seaconn=seaconn))
|
||||||
content = json.dumps(descr).replace('}, {', '},\n{')
|
content = json.dumps(descr).replace('}, {', '},\n{').replace('[{', '[\n{').replace('}]}, ', '}]},\n\n')
|
||||||
with open(join(seaconfdir, filename + '.json'), 'w') as fp:
|
with open(join(seaconfdir, filename + '.json'), 'w') as fp:
|
||||||
fp.write(content + '\n')
|
fp.write(content + '\n')
|
||||||
result.append('%s: %s' % (filename, ','.join(n for n in descr)))
|
result.append('%s: %s' % (filename, ','.join(n for n in descr)))
|
||||||
return '; '.join(result)
|
raise SystemExit('; '.join(result))
|
||||||
|
|
||||||
@Command(StringType(), result=StringType())
|
@Command(StringType(), result=StringType())
|
||||||
def query(self, cmd):
|
def query(self, cmd):
|
||||||
@ -369,11 +387,9 @@ class SeaModule(Module):
|
|||||||
paramdesc['key'] = 'value'
|
paramdesc['key'] = 'value'
|
||||||
if issubclass(cls, SeaWritable):
|
if issubclass(cls, SeaWritable):
|
||||||
if paramdesc.get('readonly', True):
|
if paramdesc.get('readonly', True):
|
||||||
raise ConfigError('%s is not writable' % sea_object)
|
raise ConfigError('%s/%s is not writable' % (sea_object, paramdesc['path']))
|
||||||
targetdesc = dict(paramdesc, key='target')
|
paramdesc['key'] = 'target'
|
||||||
params.append(targetdesc)
|
paramdesc['readonly'] = False
|
||||||
paramdesc['readonly'] = True
|
|
||||||
# print('SINGLE %s/%s %s %r' % (base, paramdesc['path'], cls.__name__, params))
|
|
||||||
extra_module_set = ()
|
extra_module_set = ()
|
||||||
if 'description' not in cfgdict:
|
if 'description' not in cfgdict:
|
||||||
cfgdict['description'] = '%s@%s' % (single_module, json_file)
|
cfgdict['description'] = '%s@%s' % (single_module, json_file)
|
||||||
@ -391,8 +407,11 @@ class SeaModule(Module):
|
|||||||
if rel_paths == '*' or not rel_paths:
|
if rel_paths == '*' or not rel_paths:
|
||||||
# take all
|
# take all
|
||||||
main = descr['params'][0]
|
main = descr['params'][0]
|
||||||
# assert main['path'] == '' # TODO: check cases where this fails
|
if issubclass(cls, Readable):
|
||||||
main['key'] = 'value'
|
# assert main['path'] == '' # TODO: check cases where this fails
|
||||||
|
main['key'] = 'value'
|
||||||
|
else:
|
||||||
|
descr['params'].pop(0)
|
||||||
else:
|
else:
|
||||||
# filter by relative paths
|
# filter by relative paths
|
||||||
rel_paths = rel_paths.split()
|
rel_paths = rel_paths.split()
|
||||||
@ -401,7 +420,11 @@ class SeaModule(Module):
|
|||||||
include = True
|
include = True
|
||||||
for paramdesc in descr['params']:
|
for paramdesc in descr['params']:
|
||||||
path = paramdesc['path']
|
path = paramdesc['path']
|
||||||
if paramdesc.get('visibility', 1) > visibility_level and not path.endswith('is_running'):
|
if path.endswith('is_running'):
|
||||||
|
# take this always
|
||||||
|
result.append(paramdesc)
|
||||||
|
continue
|
||||||
|
if paramdesc.get('visibility', 1) > visibility_level:
|
||||||
continue
|
continue
|
||||||
sub = path.split('/', 1)
|
sub = path.split('/', 1)
|
||||||
if rpath == '.': # take all except subpaths with readonly node at top
|
if rpath == '.': # take all except subpaths with readonly node at top
|
||||||
@ -412,14 +435,22 @@ class SeaModule(Module):
|
|||||||
elif sub[0] == rpath:
|
elif sub[0] == rpath:
|
||||||
result.append(paramdesc)
|
result.append(paramdesc)
|
||||||
descr['params'] = result
|
descr['params'] = result
|
||||||
rel0 = '' if rel_paths[0] == '.' else rel_paths[0]
|
for valuedesc in result:
|
||||||
if result[0]['path'] == rel0:
|
if valuedesc['path'] == '':
|
||||||
result[0]['key'] = 'value'
|
valuedesc['key'] = 'value'
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
logger.error('%s: no value found', name)
|
logger.error('%s: no value found', name)
|
||||||
# logger.info('PARAMS %s %r', name, result)
|
# logger.info('PARAMS %s %r', name, result)
|
||||||
base = descr['base']
|
base = descr['base']
|
||||||
params = descr['params']
|
params = descr['params']
|
||||||
|
if issubclass(cls, SeaWritable):
|
||||||
|
paramdesc = params[0]
|
||||||
|
assert paramdesc['key'] == 'value'
|
||||||
|
if paramdesc.get('readonly', True):
|
||||||
|
raise ConfigError('%s/%s is not writable' % (sea_object, paramdesc['path']))
|
||||||
|
paramdesc['key'] = 'target'
|
||||||
|
paramdesc['readonly'] = False
|
||||||
extra_module_set = cfgdict.pop('extra_modules', ())
|
extra_module_set = cfgdict.pop('extra_modules', ())
|
||||||
if extra_module_set:
|
if extra_module_set:
|
||||||
extra_module_set = set(extra_module_set.replace(',', ' ').split())
|
extra_module_set = set(extra_module_set.replace(',', ' ').split())
|
||||||
@ -442,21 +473,23 @@ class SeaModule(Module):
|
|||||||
if kwds['datatype'] is None:
|
if kwds['datatype'] is None:
|
||||||
kwds.update(visibility=3, default='', datatype=StringType())
|
kwds.update(visibility=3, default='', datatype=StringType())
|
||||||
pathlist = path.split('/') if path else []
|
pathlist = path.split('/') if path else []
|
||||||
key = paramdesc.get('key') # will be None, 'value' or 'target'
|
key = paramdesc.get('key') # None, 'value' or 'target'
|
||||||
if key is None:
|
if key is None:
|
||||||
if len(pathlist) > 0:
|
if len(pathlist) > 0:
|
||||||
if len(pathlist) == 1:
|
if len(pathlist) == 1:
|
||||||
kwds['group'] = 'more'
|
if issubclass(cls, Readable):
|
||||||
|
kwds['group'] = 'more'
|
||||||
else:
|
else:
|
||||||
kwds['group'] = pathlist[-2]
|
kwds['group'] = pathlist[-2]
|
||||||
# flatten path to parameter name
|
# flatten path to parameter name
|
||||||
key = None
|
|
||||||
for i in reversed(range(len(pathlist))):
|
for i in reversed(range(len(pathlist))):
|
||||||
key = '_'.join(pathlist[i:])
|
key = '_'.join(pathlist[i:])
|
||||||
if not key in cls.accessibles:
|
if not key in cls.accessibles:
|
||||||
break
|
break
|
||||||
if key == 'is_running':
|
if key == 'is_running':
|
||||||
kwds['export'] = False
|
kwds['export'] = False
|
||||||
|
if key == 'target' and kwds.get('group') == 'more':
|
||||||
|
kwds.pop('group')
|
||||||
if key in cls.accessibles:
|
if key in cls.accessibles:
|
||||||
if key == 'target':
|
if key == 'target':
|
||||||
kwds['readonly'] = False
|
kwds['readonly'] = False
|
||||||
@ -465,20 +498,21 @@ class SeaModule(Module):
|
|||||||
else:
|
else:
|
||||||
pobj = Parameter(**kwds)
|
pobj = Parameter(**kwds)
|
||||||
datatype = pobj.datatype
|
datatype = pobj.datatype
|
||||||
|
if issubclass(cls, SeaWritable) and key == 'target':
|
||||||
|
kwds['readonly'] = False
|
||||||
|
attributes['value'] = Parameter(**kwds)
|
||||||
|
|
||||||
hdbpath = '/'.join([base] + pathlist)
|
hdbpath = '/'.join([base] + pathlist)
|
||||||
if key in extra_module_set:
|
if key in extra_module_set:
|
||||||
extra_modules[name + '.' + key] = sea_object, base, paramdesc
|
extra_modules[name + '.' + key] = sea_object, base, paramdesc
|
||||||
continue # skip this parameter
|
continue # skip this parameter
|
||||||
path2param[hdbpath] = (name, key)
|
path2param[hdbpath] = (name, key)
|
||||||
# logger.info('PARAM %s %s %s', hdbpath, name, key)
|
|
||||||
attributes[key] = pobj
|
attributes[key] = pobj
|
||||||
# if hasattr(cls, 'read_' + key):
|
# if hasattr(cls, 'read_' + key):
|
||||||
# print('override %s.read_%s' % (cls.__name__, key))
|
# print('override %s.read_%s' % (cls.__name__, key))
|
||||||
|
|
||||||
def rfunc(self, cmd='hval %s/%s' % (base, path)):
|
def rfunc(self, cmd='hval %s/%s' % (base, path)):
|
||||||
print('READ', cmd)
|
|
||||||
reply = self._iodev.query(cmd)
|
reply = self._iodev.query(cmd)
|
||||||
print('REPLY', reply)
|
|
||||||
try:
|
try:
|
||||||
reply = float(reply)
|
reply = float(reply)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -489,8 +523,8 @@ class SeaModule(Module):
|
|||||||
attributes['read_' + key] = rfunc
|
attributes['read_' + key] = rfunc
|
||||||
|
|
||||||
if not readonly:
|
if not readonly:
|
||||||
if hasattr(cls, 'write_' + key):
|
# if hasattr(cls, 'write_' + key):
|
||||||
print('override %s.write_%s' % (cls.__name__, key))
|
# print('override %s.write_%s' % (cls.__name__, key))
|
||||||
|
|
||||||
def wfunc(self, value, datatype=datatype, command=paramdesc['cmd']):
|
def wfunc(self, value, datatype=datatype, command=paramdesc['cmd']):
|
||||||
value = datatype.export_value(value)
|
value = datatype.export_value(value)
|
||||||
@ -499,7 +533,6 @@ class SeaModule(Module):
|
|||||||
# TODO: check if more has to be done for valid tcl data (strings?)
|
# TODO: check if more has to be done for valid tcl data (strings?)
|
||||||
cmd = "%s %s" % (command, value)
|
cmd = "%s %s" % (command, value)
|
||||||
self._iodev.query(cmd)
|
self._iodev.query(cmd)
|
||||||
print('WRITE %s' % cmd)
|
|
||||||
return Done
|
return Done
|
||||||
|
|
||||||
attributes['write_' + key] = wfunc
|
attributes['write_' + key] = wfunc
|
||||||
@ -563,6 +596,7 @@ class SeaWritable(SeaModule, Writable):
|
|||||||
return self.target
|
return self.target
|
||||||
|
|
||||||
def update_target(self, value, timestamp, readerror):
|
def update_target(self, value, timestamp, readerror):
|
||||||
|
self.target = value
|
||||||
if not readerror:
|
if not readerror:
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ class Sensor(Readable):
|
|||||||
|
|
||||||
def update_value(self, value):
|
def update_value(self, value):
|
||||||
if self.abs:
|
if self.abs:
|
||||||
value = abs(value)
|
value = abs(float(value))
|
||||||
self.value = self._calib(value)
|
self.value = self._calib(value)
|
||||||
self._value_error = None
|
self._value_error = None
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ class Motor(PersistentMixin, HasIodev, Drivable):
|
|||||||
FloatRange(0, 360., unit='$'),
|
FloatRange(0, 360., unit='$'),
|
||||||
212, ANGLE_SCALE, readonly=False, group='more')
|
212, ANGLE_SCALE, readonly=False, group='more')
|
||||||
speed = HwParam('max. speed', FloatRange(0, MAX_SPEED, unit='$/sec'),
|
speed = HwParam('max. speed', FloatRange(0, MAX_SPEED, unit='$/sec'),
|
||||||
4, SPEED_SCALE, readonly=False, group='more')
|
4, SPEED_SCALE, readonly=False, group='motorparam')
|
||||||
minspeed = HwParam('min. speed', FloatRange(0, MAX_SPEED, unit='$/sec'),
|
minspeed = HwParam('min. speed', FloatRange(0, MAX_SPEED, unit='$/sec'),
|
||||||
130, SPEED_SCALE, readonly=False, default=SPEED_SCALE, group='motorparam')
|
130, SPEED_SCALE, readonly=False, default=SPEED_SCALE, group='motorparam')
|
||||||
currentspeed = HwParam('current speed', FloatRange(-MAX_SPEED, MAX_SPEED, unit='$/sec'),
|
currentspeed = HwParam('current speed', FloatRange(-MAX_SPEED, MAX_SPEED, unit='$/sec'),
|
||||||
@ -221,7 +221,6 @@ class Motor(PersistentMixin, HasIodev, Drivable):
|
|||||||
initialized = self.comm(GET_GLOB_PAR, 255, bank=2)
|
initialized = self.comm(GET_GLOB_PAR, 255, bank=2)
|
||||||
if initialized: # no power loss
|
if initialized: # no power loss
|
||||||
self.saveParameters()
|
self.saveParameters()
|
||||||
print('SAVED', self.persistentData)
|
|
||||||
else: # just powered up
|
else: # just powered up
|
||||||
# get persistent values
|
# get persistent values
|
||||||
writeDict = self.loadParameters()
|
writeDict = self.loadParameters()
|
||||||
@ -403,18 +402,18 @@ class Motor(PersistentMixin, HasIodev, Drivable):
|
|||||||
self.status = self.Status.IDLE, 'stopped'
|
self.status = self.Status.IDLE, 'stopped'
|
||||||
self._started = 0
|
self._started = 0
|
||||||
|
|
||||||
@Command()
|
#@Command()
|
||||||
def step(self):
|
#def step(self):
|
||||||
self.comm(MOVE, 1, FULL_STEP / ANGLE_SCALE)
|
# self.comm(MOVE, 1, FULL_STEP / ANGLE_SCALE)
|
||||||
|
|
||||||
@Command()
|
#@Command()
|
||||||
def back(self):
|
#def back(self):
|
||||||
self.comm(MOVE, 1, - FULL_STEP / ANGLE_SCALE)
|
# self.comm(MOVE, 1, - FULL_STEP / ANGLE_SCALE)
|
||||||
|
|
||||||
@Command(IntRange(), result=IntRange())
|
#@Command(IntRange(), result=IntRange())
|
||||||
def get_axis_par(self, adr):
|
#def get_axis_par(self, adr):
|
||||||
return self.comm(GET_AXIS_PAR, adr)
|
# return self.comm(GET_AXIS_PAR, adr)
|
||||||
|
|
||||||
@Command((IntRange(), FloatRange()), result=IntRange())
|
#@Command((IntRange(), FloatRange()), result=IntRange())
|
||||||
def set_axis_par(self, adr, value):
|
#def set_axis_par(self, adr, value):
|
||||||
return self.comm(SET_AXIS_PAR, adr, value)
|
# return self.comm(SET_AXIS_PAR, adr, value)
|
||||||
|
Reference in New Issue
Block a user