new poll mechanism
- remove secop.poller and basic poller - regular polls for 'important' parameters done by method doPoll - all other parameters are polled slower (slowInterval) and with lower priority (only one at a time when main poll is due) - nopoll decorator for read_* to disable poll - enablePoll attribute (default True) for disabling polling a module - fast polls may be implemented by means of a statemachine - configurable slow poll interval + allow a Parameter to override a Property (parameter Readable.pollinterval overrides Module.pollinterval) Change-Id: Ib1b3453041a233678b7c4b4add22ac399670e447 Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/27832 Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de> Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch> Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
# *****************************************************************************
|
||||
"""Andeen Hagerling capacitance bridge"""
|
||||
|
||||
from secop.core import Done, FloatRange, HasIO, Parameter, Readable, StringIO
|
||||
from secop.core import Done, FloatRange, HasIO, Parameter, Readable, StringIO, nopoll
|
||||
|
||||
|
||||
class Ah2700IO(StringIO):
|
||||
@@ -30,7 +30,7 @@ class Ah2700IO(StringIO):
|
||||
|
||||
class Capacitance(HasIO, Readable):
|
||||
|
||||
value = Parameter('capacitance', FloatRange(unit='pF'), poll=True)
|
||||
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 = Parameter('loss', FloatRange(unit='deg'), default=0)
|
||||
@@ -69,14 +69,17 @@ class Capacitance(HasIO, Readable):
|
||||
self.parse_reply(self.communicate('SI')) # SI = single trigger
|
||||
return Done
|
||||
|
||||
@nopoll
|
||||
def read_freq(self):
|
||||
self.read_value()
|
||||
return Done
|
||||
|
||||
@nopoll
|
||||
def read_loss(self):
|
||||
self.read_value()
|
||||
return Done
|
||||
|
||||
@nopoll
|
||||
def read_voltage(self):
|
||||
self.read_value()
|
||||
return Done
|
||||
|
||||
@@ -43,11 +43,11 @@ SOURCECMDS = {
|
||||
|
||||
class SourceMeter(HasIO, Module):
|
||||
|
||||
resistivity = Parameter('readback resistivity', FloatRange(unit='Ohm'), poll=True)
|
||||
power = Parameter('readback power', FloatRange(unit='W'), poll=True)
|
||||
resistivity = Parameter('readback resistivity', FloatRange(unit='Ohm'))
|
||||
power = Parameter('readback power', FloatRange(unit='W'))
|
||||
mode = Parameter('measurement mode', EnumType(off=0, current=1, voltage=2),
|
||||
readonly=False, default=0)
|
||||
active = Parameter('output enable', BoolType(), readonly=False, poll=True)
|
||||
active = Parameter('output enable', BoolType(), readonly=False)
|
||||
|
||||
ioClass = K2601bIO
|
||||
|
||||
@@ -76,10 +76,10 @@ class SourceMeter(HasIO, Module):
|
||||
class Current(HasIO, Writable):
|
||||
sourcemeter = Attached()
|
||||
|
||||
value = Parameter('measured current', FloatRange(unit='A'), poll=True)
|
||||
target = Parameter('set current', FloatRange(unit='A'), poll=True)
|
||||
value = Parameter('measured current', FloatRange(unit='A'))
|
||||
target = Parameter('set current', FloatRange(unit='A'))
|
||||
active = Parameter('current is controlled', BoolType(), default=False) # polled from Current/Voltage
|
||||
limit = Parameter('current limit', FloatRange(0, 2.0, unit='A'), default=2, poll=True)
|
||||
limit = Parameter('current limit', FloatRange(0, 2.0, unit='A'), default=2)
|
||||
|
||||
def read_value(self):
|
||||
return self.communicate('print(smua.measure.i())')
|
||||
@@ -119,10 +119,10 @@ class Current(HasIO, Writable):
|
||||
class Voltage(HasIO, Writable):
|
||||
sourcemeter = Attached()
|
||||
|
||||
value = Parameter('measured voltage', FloatRange(unit='V'), poll=True)
|
||||
target = Parameter('set voltage', FloatRange(unit='V'), poll=True)
|
||||
active = Parameter('voltage is controlled', BoolType(), poll=True)
|
||||
limit = Parameter('current limit', FloatRange(0, 2.0, unit='V'), default=2, poll=True)
|
||||
value = Parameter('measured voltage', FloatRange(unit='V'))
|
||||
target = Parameter('set voltage', FloatRange(unit='V'))
|
||||
active = Parameter('voltage is controlled', BoolType())
|
||||
limit = Parameter('current limit', FloatRange(0, 2.0, unit='V'), default=2)
|
||||
|
||||
def read_value(self):
|
||||
return self.communicate('print(smua.measure.v())')
|
||||
|
||||
@@ -27,7 +27,6 @@ from secop.datatypes import BoolType, EnumType, FloatRange, IntRange
|
||||
from secop.lib import formatStatusBits
|
||||
from secop.modules import Attached, Done, \
|
||||
Drivable, Parameter, Property, Readable
|
||||
from secop.poller import REGULAR, Poller
|
||||
from secop.io import HasIO
|
||||
|
||||
Status = Drivable.Status
|
||||
@@ -60,12 +59,11 @@ class StringIO(secop.io.StringIO):
|
||||
|
||||
class Main(HasIO, Drivable):
|
||||
|
||||
value = Parameter('the current channel', poll=REGULAR, datatype=IntRange(0, 17))
|
||||
value = Parameter('the current channel', datatype=IntRange(0, 17))
|
||||
target = Parameter('channel to select', datatype=IntRange(0, 17))
|
||||
autoscan = Parameter('whether to scan automatically', datatype=BoolType(), readonly=False, default=False)
|
||||
pollinterval = Parameter(default=1, export=False)
|
||||
|
||||
pollerClass = Poller
|
||||
ioClass = StringIO
|
||||
_channel_changed = 0 # time of last channel change
|
||||
_channels = None # dict <channel no> of <module object>
|
||||
@@ -141,7 +139,6 @@ class ResChannel(HasIO, Readable):
|
||||
enumerate(mag % val for mag in ['%guV', '%gmV']
|
||||
for val in [2, 6.32, 20, 63.2, 200, 632]))}
|
||||
|
||||
pollerClass = Poller
|
||||
ioClass = StringIO
|
||||
_main = None # main module
|
||||
_last_range_change = 0 # time of last range change
|
||||
|
||||
@@ -42,7 +42,6 @@ from secop.lib import clamp
|
||||
from secop.lib.enum import Enum
|
||||
from secop.modules import Communicator, Done, \
|
||||
Drivable, Parameter, Property, Readable
|
||||
from secop.poller import Poller
|
||||
from secop.io import HasIO
|
||||
from secop.rwhandler import CommonReadHandler, CommonWriteHandler
|
||||
|
||||
@@ -57,7 +56,7 @@ class Main(Communicator):
|
||||
"""ppms communicator module"""
|
||||
|
||||
pollinterval = Parameter('poll interval', FloatRange(), readonly=False, default=2)
|
||||
data = Parameter('internal', StringType(), poll=True, export=True, # export for test only
|
||||
data = Parameter('internal', StringType(), export=True, # export for test only
|
||||
default="", readonly=True)
|
||||
|
||||
class_id = Property('Quantum Design class id', StringType(), export=False)
|
||||
@@ -70,8 +69,6 @@ class Main(Communicator):
|
||||
_channel_to_index = dict(((channel, i) for i, channel in enumerate(_channel_names)))
|
||||
_status_bitpos = {'temp': 0, 'field': 4, 'chamber': 8, 'position': 12}
|
||||
|
||||
pollerClass = Poller
|
||||
|
||||
def earlyInit(self):
|
||||
super().earlyInit()
|
||||
self.modules = {}
|
||||
@@ -89,6 +86,9 @@ class Main(Communicator):
|
||||
self.comLog("< %s", reply)
|
||||
return reply
|
||||
|
||||
def doPoll(self):
|
||||
self.read_data()
|
||||
|
||||
def read_data(self):
|
||||
mask = 1 # always get packed_status
|
||||
for channelname, channel in self.modules.items():
|
||||
@@ -116,12 +116,9 @@ class Main(Communicator):
|
||||
|
||||
class PpmsBase(HasIO, Readable):
|
||||
"""common base for all ppms modules"""
|
||||
# polling is done by the main module
|
||||
# and PPMS does not deliver really more fresh values when polled more often
|
||||
value = Parameter(poll=False, needscfg=False)
|
||||
status = Parameter(poll=False, needscfg=False)
|
||||
value = Parameter(needscfg=False)
|
||||
status = Parameter(needscfg=False)
|
||||
|
||||
pollerClass = Poller
|
||||
enabled = True # default, if no parameter enable is defined
|
||||
_last_settings = None # used by several modules
|
||||
slow_pollfactor = 1
|
||||
@@ -134,6 +131,11 @@ class PpmsBase(HasIO, Readable):
|
||||
super().initModule()
|
||||
self.io.register(self)
|
||||
|
||||
def doPoll(self):
|
||||
# polling is done by the main module
|
||||
# and PPMS does not deliver really more fresh values when polled more often
|
||||
pass
|
||||
|
||||
def update_value_status(self, value, packed_status):
|
||||
# update value and status
|
||||
# to be reimplemented for modules looking at packed_status
|
||||
@@ -157,7 +159,7 @@ class Channel(PpmsBase):
|
||||
"""channel base class"""
|
||||
|
||||
value = Parameter('main value of channels')
|
||||
enabled = Parameter('is this channel used?', readonly=False, poll=False,
|
||||
enabled = Parameter('is this channel used?', readonly=False,
|
||||
datatype=BoolType(), default=False)
|
||||
|
||||
channel = Property('channel name',
|
||||
@@ -189,7 +191,7 @@ class UserChannel(Channel):
|
||||
class DriverChannel(Channel):
|
||||
"""driver channel"""
|
||||
|
||||
current = Parameter('driver current', readonly=False, poll=True, # poll only one parameter
|
||||
current = Parameter('driver current', readonly=False,
|
||||
datatype=FloatRange(0., 5000., unit='uA'))
|
||||
powerlimit = Parameter('power limit', readonly=False,
|
||||
datatype=FloatRange(0., 1000., unit='uW'))
|
||||
@@ -217,7 +219,7 @@ class DriverChannel(Channel):
|
||||
class BridgeChannel(Channel):
|
||||
"""bridge channel"""
|
||||
|
||||
excitation = Parameter('excitation current', readonly=False, poll=True, # poll only one parameter
|
||||
excitation = Parameter('excitation current', readonly=False,
|
||||
datatype=FloatRange(0.01, 5000., unit='uA'))
|
||||
powerlimit = Parameter('power limit', readonly=False,
|
||||
datatype=FloatRange(0.001, 1000., unit='uW'))
|
||||
@@ -263,10 +265,13 @@ class BridgeChannel(Channel):
|
||||
class Level(PpmsBase):
|
||||
"""helium level"""
|
||||
|
||||
value = Parameter(datatype=FloatRange(unit='%'), poll=True)
|
||||
value = Parameter(datatype=FloatRange(unit='%'))
|
||||
|
||||
channel = 'level'
|
||||
|
||||
def doPoll(self):
|
||||
self.read_value()
|
||||
|
||||
def update_value_status(self, value, packed_status):
|
||||
pass
|
||||
# must be a no-op
|
||||
@@ -303,8 +308,8 @@ class Chamber(PpmsBase, Drivable):
|
||||
name2opcode = {k: v for _, _, _, v, k in code_table if k}
|
||||
opcode2name = {v: k for _, _, _, v, k in code_table if k}
|
||||
status_map = {v: (c, k.replace('_', ' ')) for v, c, k, _, _ in code_table}
|
||||
value = Parameter(description='chamber state', datatype=EnumType(**value_codes), default=0, poll=True)
|
||||
target = Parameter(description='chamber command', datatype=EnumType(**target_codes), default='noop', poll=True)
|
||||
value = Parameter(description='chamber state', datatype=EnumType(**value_codes), default=0)
|
||||
target = Parameter(description='chamber command', datatype=EnumType(**target_codes), default='noop')
|
||||
|
||||
channel = 'chamber'
|
||||
|
||||
@@ -339,9 +344,9 @@ class Temp(PpmsBase, Drivable):
|
||||
)
|
||||
value = Parameter(datatype=FloatRange(unit='K'))
|
||||
status = Parameter(datatype=StatusType(Status))
|
||||
target = Parameter(datatype=FloatRange(1.7, 402.0, unit='K'), poll=False, needscfg=False)
|
||||
target = Parameter(datatype=FloatRange(1.7, 402.0, unit='K'), needscfg=False)
|
||||
setpoint = Parameter('intermediate set point',
|
||||
datatype=FloatRange(1.7, 402.0, unit='K'), poll=True) # poll only one parameter
|
||||
datatype=FloatRange(1.7, 402.0, unit='K'))
|
||||
ramp = Parameter('ramping speed', readonly=False, default=0,
|
||||
datatype=FloatRange(0, 20, unit='K/min'))
|
||||
workingramp = Parameter('intermediate ramp value',
|
||||
@@ -509,7 +514,7 @@ class Field(PpmsBase, Drivable):
|
||||
)
|
||||
value = Parameter(datatype=FloatRange(unit='T'))
|
||||
status = Parameter(datatype=StatusType(Status))
|
||||
target = Parameter(datatype=FloatRange(-15, 15, unit='T'), poll=True) # poll only one parameter
|
||||
target = Parameter(datatype=FloatRange(-15, 15, unit='T')) # poll only one parameter
|
||||
ramp = Parameter('ramping speed', readonly=False,
|
||||
datatype=FloatRange(0.064, 1.19, unit='T/min'), default=0.19)
|
||||
approachmode = Parameter('how to approach target', readonly=False,
|
||||
@@ -640,8 +645,8 @@ class Position(PpmsBase, Drivable):
|
||||
Status = Drivable.Status
|
||||
|
||||
value = Parameter(datatype=FloatRange(unit='deg'))
|
||||
target = Parameter(datatype=FloatRange(-720., 720., unit='deg'), poll=True) # poll only one parameter
|
||||
enabled = Parameter('is this channel used?', readonly=False, poll=False,
|
||||
target = Parameter(datatype=FloatRange(-720., 720., unit='deg'))
|
||||
enabled = Parameter('is this channel used?', readonly=False,
|
||||
datatype=BoolType(), default=True)
|
||||
speed = Parameter('motor speed', readonly=False, default=12,
|
||||
datatype=FloatRange(0.8, 12, unit='deg/sec'))
|
||||
|
||||
@@ -160,9 +160,9 @@ class Sensor(Readable):
|
||||
pollinterval = Parameter(export=False)
|
||||
status = Parameter(default=(Readable.Status.ERROR, 'unintialized'))
|
||||
|
||||
pollerClass = None
|
||||
description = 'a calibrated sensor value'
|
||||
_value_error = None
|
||||
enablePoll = False
|
||||
|
||||
def initModule(self):
|
||||
self._rawsensor.registerCallbacks(self, ['status']) # auto update status
|
||||
|
||||
@@ -74,7 +74,7 @@ STEPPOS_ADR = 1
|
||||
|
||||
def writable(*args, **kwds):
|
||||
"""convenience function to create writable hardware parameters"""
|
||||
return PersistentParam(*args, readonly=False, poll=True, initwrite=True, **kwds)
|
||||
return PersistentParam(*args, readonly=False, initwrite=True, **kwds)
|
||||
|
||||
|
||||
class Motor(PersistentMixin, HasIO, Drivable):
|
||||
@@ -83,9 +83,9 @@ class Motor(PersistentMixin, HasIO, Drivable):
|
||||
value = Parameter('motor position', FloatRange(unit='deg', fmtstr='%.3f'))
|
||||
zero = PersistentParam('zero point', FloatRange(unit='$'), readonly=False, default=0)
|
||||
encoder = PersistentParam('encoder reading', FloatRange(unit='$', fmtstr='%.1f'),
|
||||
readonly=True, initwrite=False, poll=True)
|
||||
readonly=True, initwrite=False)
|
||||
steppos = PersistentParam('position from motor steps', FloatRange(unit='$', fmtstr='%.3f'),
|
||||
readonly=True, initwrite=False, poll=True)
|
||||
readonly=True, initwrite=False)
|
||||
target = Parameter('', FloatRange(unit='$'), default=0)
|
||||
|
||||
move_limit = Parameter('max. angle to drive in one go', FloatRange(unit='$'),
|
||||
@@ -98,26 +98,26 @@ class Motor(PersistentMixin, HasIO, Drivable):
|
||||
minspeed = writable('min. speed', FloatRange(0, MAX_SPEED, unit='$/sec', fmtstr='%.1f'),
|
||||
default=SPEED_SCALE, group='motorparam')
|
||||
currentspeed = Parameter('current speed', FloatRange(-MAX_SPEED, MAX_SPEED, unit='$/sec', fmtstr='%.1f'),
|
||||
poll=True, group='motorparam')
|
||||
group='motorparam')
|
||||
maxcurrent = writable('', FloatRange(0, 2.8, unit='A', fmtstr='%.2f'),
|
||||
default=1.4, group='motorparam')
|
||||
standby_current = writable('', FloatRange(0, 2.8, unit='A', fmtstr='%.2f'),
|
||||
default=0.1, group='motorparam')
|
||||
acceleration = writable('', FloatRange(4.6 * ACCEL_SCALE, MAX_ACCEL, unit='deg/s^2', fmtstr='%.1f'),
|
||||
default=150., group='motorparam')
|
||||
target_reached = Parameter('', BoolType(), poll=True, group='hwstatus')
|
||||
move_status = Parameter('', IntRange(0, 3), poll=True, group='hwstatus')
|
||||
error_bits = Parameter('', IntRange(0, 255), poll=True, group='hwstatus')
|
||||
target_reached = Parameter('', BoolType(), group='hwstatus')
|
||||
move_status = Parameter('', IntRange(0, 3), group='hwstatus')
|
||||
error_bits = Parameter('', IntRange(0, 255), group='hwstatus')
|
||||
free_wheeling = writable('', FloatRange(0, 60., unit='sec', fmtstr='%.2f'),
|
||||
default=0.1, group='motorparam')
|
||||
power_down_delay = writable('', FloatRange(0, 60., unit='sec', fmtstr='%.2f'),
|
||||
default=0.1, group='motorparam')
|
||||
baudrate = Parameter('', EnumType({'%d' % v: i for i, v in enumerate(BAUDRATES)}),
|
||||
readonly=False, default=0, poll=True, visibility=3, group='more')
|
||||
readonly=False, default=0, visibility=3, group='more')
|
||||
pollinterval = Parameter(group='more')
|
||||
|
||||
ioClass = BytesIO
|
||||
fast_pollfactor = 0.001 # poll as fast as possible when busy
|
||||
fast_pollfactor = 0.001 # not used any more, TODO: use a statemachine for running
|
||||
_started = 0
|
||||
_calcTimeout = True
|
||||
_need_reset = None
|
||||
|
||||
Reference in New Issue
Block a user