[MLZ] fix entangle integration
handling of mappings for NamedDigital*put needs to be improved! Change-Id: I015cb1d26d049d3caecc0e03baa9f523951f004c Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/22932 Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de> Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de>
This commit is contained in:
parent
ac03f5333f
commit
bccfe6109b
@ -1,5 +1,5 @@
|
||||
[node MLZ_ccr12]
|
||||
description = CCR12 box of MLZ Sample environment group
|
||||
description = CCR box of MLZ Sample environment group
|
||||
.
|
||||
Contains a Lakeshore 336 and an PLC controlling the compressor
|
||||
and some valves.
|
||||
@ -14,58 +14,86 @@ bindport=10767
|
||||
class=secop_mlz.entangle.NamedDigitalOutput
|
||||
tangodevice=tango://localhost:10000/box/plc/_automatik
|
||||
mapping=dict(Off=0,p1=1,p2=2)
|
||||
description="controls the (simple) pressure regulation
|
||||
.
|
||||
selects between off, regulate on p1 or regulate on p2 sensor"
|
||||
|
||||
[module compressor]
|
||||
class=secop_mlz.entangle.NamedDigitalOutput
|
||||
tangodevice=tango://localhost:10000/box/plc/_cooler_onoff
|
||||
mapping=dict(Off=0,On=1)
|
||||
description=control the compressor (on/off)
|
||||
|
||||
[module gas]
|
||||
class=secop_mlz.entangle.NamedDigitalOutput
|
||||
tangodevice=tango://localhost:10000/box/plc/_gas_onoff
|
||||
mapping=dict(Off=0,On=1)
|
||||
description=control the gas inlet into the ccr (on/off)
|
||||
.
|
||||
note: this switches off automatically after 15 min.
|
||||
note: activation de-activates the vacuum inlet
|
||||
note: if the pressure regulation is active, it enslave this device
|
||||
|
||||
[module vacuum]
|
||||
class=secop_mlz.entangle.NamedDigitalOutput
|
||||
tangodevice=tango://localhost:10000/box/plc/_vacuum_Onoff
|
||||
mapping=dict(Off=0,On=1)
|
||||
description=control the vacuum inlet into the ccr (on/off)
|
||||
.
|
||||
note: activation de-activates the gas inlet
|
||||
note: if the pressure regulation is active, it enslave this device
|
||||
|
||||
[module p1]
|
||||
class=secop_mlz.entangle.AnalogInput
|
||||
tangodevice=tango://localhost:10000/box/plc/_p1
|
||||
value.unit='mbar'
|
||||
description=pressure sensor 1 (linear scale)
|
||||
|
||||
[module p2]
|
||||
class=secop_mlz.entangle.AnalogInput
|
||||
tangodevice=tango://localhost:10000/box/plc/_p2
|
||||
value.unit='mbar'
|
||||
description=pressure sensor 2 (selectable curve)
|
||||
|
||||
[module curve_p2]
|
||||
class=secop_mlz.entangle.NamedDigitalInput
|
||||
tangodevice=tango://localhost:10000/box/plc/_curve
|
||||
value.default='undefined'
|
||||
mapping=dict(curve1=1,curve2=2,curve3=3)
|
||||
value.default=0
|
||||
description=calibration curve for pressure sensor 2
|
||||
mapping="{'0-10V':0, '0-1000mbar':1, '1-9V to 0-1 mbar':2,
|
||||
'DI200':3, 'DI2000':4, 'TTR100':7, 'PTR90':8,
|
||||
'PTR225/237':9, 'ITR90':10, 'ITR100-D':11,
|
||||
'ITR100-2':12, 'ITR100-3':13, 'ITR100-4':14,
|
||||
'ITR100-5':15, 'ITR100-6':16, 'ITR100-7':17,
|
||||
'ITR100-8':18, 'ITR100-9':19, 'ITR100-A':20,
|
||||
'CMR361':21, 'CMR362':22, 'CMR363':23,
|
||||
'CMR364':24, 'CMR365':25}"
|
||||
|
||||
# sensors
|
||||
[module T_sample]
|
||||
class=secop_mlz.entangle.Sensor
|
||||
tangodevice=tango://localhost:10000/box/sample/sensora
|
||||
value.unit='K'
|
||||
description=sample temperature
|
||||
|
||||
[module T_stick]
|
||||
class=secop_mlz.entangle.Sensor
|
||||
tangodevice=tango://localhost:10000/box/stick/sensorb
|
||||
value.unit='K'
|
||||
description=temperature at bottom of sample stick
|
||||
|
||||
[module T_coldhead]
|
||||
class=secop_mlz.entangle.Sensor
|
||||
tangodevice=tango://localhost:10000/box/coldhead/sensorc
|
||||
value.unit='K'
|
||||
description=temperature at coldhead
|
||||
|
||||
[module T_tube]
|
||||
class=secop_mlz.entangle.Sensor
|
||||
tangodevice=tango://localhost:10000/box/tube/sensord
|
||||
value.unit='K'
|
||||
description=temperature at thermal coupling tube <-> stick
|
||||
|
||||
|
||||
# regulations
|
||||
|
||||
@ -73,6 +101,7 @@ value.unit='K'
|
||||
class=secop_mlz.entangle.TemperatureController
|
||||
tangodevice=tango://localhost:10000/box/stick/control2
|
||||
heateroutput.default=0
|
||||
description=regulation of stick temperature
|
||||
ramp.default=6
|
||||
speed.default=0.1
|
||||
setpoint.default=0
|
||||
@ -89,11 +118,13 @@ class=secop_mlz.entangle.AnalogOutput
|
||||
tangodevice=tango://localhost:10000/box/stick/range2
|
||||
precision.default=1
|
||||
abslimits=(0,3)
|
||||
description=heaterrange for stick regulation
|
||||
|
||||
|
||||
[module T_tube_regulation]
|
||||
class=secop_mlz.entangle.TemperatureController
|
||||
tangodevice=tango://localhost:10000/box/tube/control1
|
||||
description=regulation of tube temperature
|
||||
heateroutput.default=0
|
||||
ramp.default=6
|
||||
speed.default=0.1
|
||||
@ -116,4 +147,4 @@ value.unit='K'
|
||||
class=secop_mlz.entangle.NamedDigitalOutput
|
||||
tangodevice=tango://localhost:10000/box/tube/range1
|
||||
mapping=dict(Off=0, Low=1, Medium=2, High=3)
|
||||
|
||||
description=heaterrange for tube regulation
|
@ -26,10 +26,10 @@
|
||||
|
||||
|
||||
import sys
|
||||
import math
|
||||
from base64 import b64decode, b64encode
|
||||
|
||||
from secop.errors import ProgrammingError, ProtocolError, BadValueError, ConfigError
|
||||
from secop.lib import clamp
|
||||
from secop.lib.enum import Enum
|
||||
from secop.parse import Parser
|
||||
from secop.properties import HasProperties, Property
|
||||
@ -160,8 +160,8 @@ class Stub(DataType):
|
||||
class FloatRange(DataType):
|
||||
"""Restricted float type"""
|
||||
properties = {
|
||||
'min': Property('low limit', Stub('FloatRange'), extname='min', default=float('-inf')),
|
||||
'max': Property('high limit', Stub('FloatRange'), extname='max', default=float('+inf')),
|
||||
'min': Property('low limit', Stub('FloatRange'), extname='min', default=-sys.float_info.max),
|
||||
'max': Property('high limit', Stub('FloatRange'), extname='max', default=sys.float_info.max),
|
||||
'unit': Property('physical unit', Stub('StringType'), extname='unit', default=''),
|
||||
'fmtstr': Property('format string', Stub('StringType'), extname='fmtstr', default='%g'),
|
||||
'absolute_resolution': Property('absolute resolution', Stub('FloatRange', 0),
|
||||
@ -172,10 +172,8 @@ class FloatRange(DataType):
|
||||
|
||||
def __init__(self, minval=None, maxval=None, **kwds):
|
||||
super().__init__()
|
||||
if minval is not None:
|
||||
kwds['min'] = minval
|
||||
if maxval is not None:
|
||||
kwds['max'] = maxval
|
||||
kwds['min'] = minval if minval is not None else -sys.float_info.max
|
||||
kwds['max'] = maxval if maxval is not None else sys.float_info.max
|
||||
self.set_properties(**kwds)
|
||||
|
||||
def checkProperties(self):
|
||||
@ -192,9 +190,10 @@ class FloatRange(DataType):
|
||||
value = float(value)
|
||||
except Exception:
|
||||
raise BadValueError('Can not __call__ %r to float' % value)
|
||||
if math.isinf(value):
|
||||
raise BadValueError('FloatRange does not accept infinity')
|
||||
# map +/-infty to +/-max possible number
|
||||
value = clamp(-sys.float_info.max, value, sys.float_info.max)
|
||||
|
||||
# now check the limits
|
||||
prec = max(abs(value * self.relative_resolution), self.absolute_resolution)
|
||||
if self.min - prec <= value <= self.max + prec:
|
||||
return min(max(value, self.min), self.max)
|
||||
|
@ -36,7 +36,7 @@ from time import sleep
|
||||
import PyTango
|
||||
|
||||
from secop.datatypes import ArrayOf, EnumType, \
|
||||
FloatRange, IntRange, StringType, TupleOf
|
||||
FloatRange, IntRange, StringType, TupleOf, LimitsType
|
||||
from secop.errors import CommunicationFailedError, \
|
||||
ConfigError, HardwareError, ProgrammingError
|
||||
from secop.lib import lazy_property
|
||||
@ -429,30 +429,26 @@ class AnalogOutput(PyTangoDevice, Drivable):
|
||||
|
||||
parameters = {
|
||||
'userlimits': Parameter('User defined limits of device value',
|
||||
datatype=TupleOf(FloatRange(), FloatRange()),
|
||||
datatype=LimitsType(FloatRange(unit='$')),
|
||||
default=(float('-Inf'), float('+Inf')),
|
||||
unit='main', readonly=False, poll=10,
|
||||
readonly=False, poll=10,
|
||||
),
|
||||
'abslimits': Parameter('Absolute limits of device value',
|
||||
datatype=TupleOf(FloatRange(), FloatRange()),
|
||||
unit='main',
|
||||
datatype=LimitsType(FloatRange(unit='$')),
|
||||
),
|
||||
'precision': Parameter('Precision of the device value (allowed deviation '
|
||||
'of stable values from target)',
|
||||
unit='main', datatype=FloatRange(1e-38),
|
||||
datatype=FloatRange(1e-38, unit='$'),
|
||||
readonly=False, group='stability',
|
||||
),
|
||||
'window': Parameter('Time window for checking stabilization if > 0',
|
||||
unit='s', default=60.0, readonly=False,
|
||||
datatype=FloatRange(0, 900), group='stability',
|
||||
),
|
||||
default=60.0, readonly=False,
|
||||
datatype=FloatRange(0, 900, unit='s'), group='stability',
|
||||
),
|
||||
'timeout': Parameter('Timeout for waiting for a stable value (if > 0)',
|
||||
unit='s', default=60.0, readonly=False,
|
||||
datatype=FloatRange(0, 900), group='stability',
|
||||
),
|
||||
}
|
||||
commands = {
|
||||
'stop': Command('Stops current movement.', argument=None, result=None),
|
||||
default=60.0, readonly=False,
|
||||
datatype=FloatRange(0, 900, unit='s'), group='stability',
|
||||
),
|
||||
}
|
||||
_history = ()
|
||||
_timeout = None
|
||||
@ -607,12 +603,12 @@ class Actuator(AnalogOutput):
|
||||
|
||||
parameters = {
|
||||
'speed': Parameter('The speed of changing the value',
|
||||
unit='main/s', readonly=False, datatype=FloatRange(0),
|
||||
readonly=False, datatype=FloatRange(0, unit='$/s'),
|
||||
),
|
||||
'ramp': Parameter('The speed of changing the value',
|
||||
unit='main/min', readonly=False, datatype=FloatRange(0),
|
||||
poll=30,
|
||||
),
|
||||
readonly=False, datatype=FloatRange(0, unit='$/s'),
|
||||
poll=30,
|
||||
),
|
||||
}
|
||||
|
||||
commands = {
|
||||
@ -647,13 +643,13 @@ class Motor(Actuator):
|
||||
|
||||
parameters = {
|
||||
'refpos': Parameter('Reference position',
|
||||
datatype=FloatRange(), unit='main',
|
||||
datatype=FloatRange(unit='$'),
|
||||
),
|
||||
'accel': Parameter('Acceleration',
|
||||
datatype=FloatRange(), readonly=False, unit='main/s^2',
|
||||
datatype=FloatRange(unit='$/s^2'), readonly=False,
|
||||
),
|
||||
'decel': Parameter('Deceleration',
|
||||
datatype=FloatRange(), readonly=False, unit='main/s^2',
|
||||
datatype=FloatRange(unit='$/s^2'), readonly=False,
|
||||
),
|
||||
}
|
||||
|
||||
@ -699,18 +695,17 @@ class TemperatureController(Actuator):
|
||||
datatype=TupleOf(FloatRange(), FloatRange(), FloatRange()),
|
||||
readonly=False, group='pid', poll=30,
|
||||
),
|
||||
'setpoint': Parameter('Current setpoint', datatype=FloatRange(), poll=1,
|
||||
'setpoint': Parameter('Current setpoint', datatype=FloatRange(unit='$'), poll=1,
|
||||
),
|
||||
'heateroutput': Parameter('Heater output', datatype=FloatRange(), poll=1,
|
||||
),
|
||||
'ramp': Parameter('Temperature ramp', unit='main/min',
|
||||
datatype=FloatRange(), readonly=False, poll=30),
|
||||
}
|
||||
|
||||
overrides = {
|
||||
# We want this to be freely user-settable, and not produce a warning
|
||||
# on startup, so select a usually sensible default.
|
||||
'precision': Override(default=0.1),
|
||||
'ramp': Override(description='Temperature ramp'),
|
||||
}
|
||||
|
||||
def read_ramp(self):
|
||||
@ -761,12 +756,13 @@ class PowerSupply(Actuator):
|
||||
"""
|
||||
|
||||
parameters = {
|
||||
'ramp': Parameter('Current/voltage ramp', unit='main/min',
|
||||
datatype=FloatRange(), readonly=False, poll=30,),
|
||||
'voltage': Parameter('Actual voltage', unit='V',
|
||||
datatype=FloatRange(), poll=-5),
|
||||
'current': Parameter('Actual current', unit='A',
|
||||
datatype=FloatRange(), poll=-5),
|
||||
'voltage': Parameter('Actual voltage',
|
||||
datatype=FloatRange(unit='V'), poll=-5),
|
||||
'current': Parameter('Actual current',
|
||||
datatype=FloatRange(unit='A'), poll=-5),
|
||||
}
|
||||
overrides = {
|
||||
'ramp': Override(description='Current/voltage ramp'),
|
||||
}
|
||||
|
||||
def read_ramp(self):
|
||||
@ -807,7 +803,11 @@ class NamedDigitalInput(DigitalInput):
|
||||
super(NamedDigitalInput, self).initModule()
|
||||
try:
|
||||
# pylint: disable=eval-used
|
||||
self.accessibles['value'].datatype = EnumType('value', **eval(self.mapping))
|
||||
mapping = eval(self.mapping.replace('\n', ' '))
|
||||
if isinstance(mapping, str):
|
||||
# pylint: disable=eval-used
|
||||
mapping = eval(mapping)
|
||||
self.accessibles['value'].setProperty('datatype', EnumType('value', **mapping))
|
||||
except Exception as e:
|
||||
raise ValueError('Illegal Value for mapping: %r' % e)
|
||||
|
||||
@ -874,9 +874,12 @@ class NamedDigitalOutput(DigitalOutput):
|
||||
super(NamedDigitalOutput, self).initModule()
|
||||
try:
|
||||
# pylint: disable=eval-used
|
||||
self.accessibles['value'].datatype = EnumType('value', **eval(self.mapping))
|
||||
# pylint: disable=eval-used
|
||||
self.accessibles['target'].datatype = EnumType('target', **eval(self.mapping))
|
||||
mapping = eval(self.mapping.replace('\n', ' '))
|
||||
if isinstance(mapping, str):
|
||||
# pylint: disable=eval-used
|
||||
mapping = eval(mapping)
|
||||
self.accessibles['value'].setProperty('datatype', EnumType('value', **mapping))
|
||||
self.accessibles['target'].setProperty('datatype', EnumType('target', **mapping))
|
||||
except Exception as e:
|
||||
raise ValueError('Illegal Value for mapping: %r' % e)
|
||||
|
||||
@ -924,8 +927,8 @@ class StringIO(PyTangoDevice, Module):
|
||||
|
||||
parameters = {
|
||||
'bustimeout': Parameter('Communication timeout',
|
||||
datatype=FloatRange(), readonly=False,
|
||||
unit='s', group='communication'),
|
||||
datatype=FloatRange(unit='s'), readonly=False,
|
||||
group='communication'),
|
||||
'endofline': Parameter('End of line',
|
||||
datatype=StringType(), readonly=False,
|
||||
group='communication'),
|
||||
|
Loading…
x
Reference in New Issue
Block a user