fixes for attocube

Change-Id: Id5eeb749ba010fec59d1c2f8a3258ee34a47e246
This commit is contained in:
2024-03-20 16:59:04 +01:00
parent ea8570d422
commit 16b826394f
2 changed files with 19 additions and 50 deletions

View File

@ -7,9 +7,10 @@ Mod('r',
'frappy_psi.attocube.Axis', 'frappy_psi.attocube.Axis',
'ANRv220-F3-02882', 'ANRv220-F3-02882',
axis = 1, axis = 1,
unit = 'deg', value = Param(unit='deg'),
tolerance = 0.01, tolerance = 0.01,
target_limits = (0, 360), target_min = 0,
target_max = 360
# gear = 1.2, # gear = 1.2,
) )

View File

@ -19,7 +19,8 @@
import sys import sys
import time import time
from frappy.core import Drivable, Parameter, Command, Property, ERROR, WARN, BUSY, IDLE, Done, nopoll, TupleOf from frappy.core import Drivable, Parameter, Command, Property, \
ERROR, WARN, BUSY, IDLE, Done, nopoll, Limit
# from frappy.features import HasSimpleOffset # from frappy.features import HasSimpleOffset
from frappy.datatypes import IntRange, FloatRange, StringType, BoolType from frappy.datatypes import IntRange, FloatRange, StringType, BoolType
from frappy.errors import ConfigError, BadValueError from frappy.errors import ConfigError, BadValueError
@ -30,50 +31,18 @@ from PyANC350v4 import Positioner
DIRECTION_NAME = {1: 'forward', -1: 'backward'} DIRECTION_NAME = {1: 'forward', -1: 'backward'}
class FreezeStatus: class Axis(Drivable):
"""freeze status for some time
hardware quite often does not treat status correctly: on a target change it
may take some time to return the 'busy' status correctly.
in classes with this mixin, within :meth:`write_target` call
self.freeze_status(0.5, BUSY, 'changed target')
a wrapper around read_status will take care that the status will be the given value,
for at least the given delay. This does NOT cover the case when self.status is set
directly from an other method.
"""
__freeze_status_until = 0
def __init_subclass__(cls):
def wrapped(self, inner=cls.read_status):
if time.time() < self.__freeze_status_until:
return Done
return inner(self)
wrapped.poll = True
cls.read_status = wrapped
super().__init_subclass__()
def freeze_status(self, delay, code=BUSY, text='changed target'):
"""freezze status to the given value for the given delay"""
self.__freeze_status_until = time.time() + delay
self.status = code, text
class Axis(FreezeStatus, Drivable):
axis = Property('axis number', IntRange(0, 2), 0) axis = Property('axis number', IntRange(0, 2), 0)
value = Parameter('axis position', FloatRange(unit='deg')) value = Parameter('axis position', FloatRange(unit='deg'))
frequency = Parameter('frequency', FloatRange(1, unit='Hz'), readonly=False) frequency = Parameter('frequency', FloatRange(1, unit='Hz'), readonly=False)
amplitude = Parameter('amplitude', FloatRange(0, unit='V'), readonly=False) amplitude = Parameter('amplitude', FloatRange(0, unit='V'), readonly=False)
gear = Parameter('gear factor', FloatRange(), readonly=False, default=1) gear = Parameter('gear factor', FloatRange(), readonly=False, value=1)
tolerance = Parameter('positioning tolerance', FloatRange(0, unit='$'), readonly=False, default=0.01) tolerance = Parameter('positioning tolerance', FloatRange(0, unit='$'), readonly=False, default=0.01)
output = Parameter('enable output', BoolType(), readonly=False) output = Parameter('enable output', BoolType(), readonly=False)
info = Parameter('axis info', StringType()) info = Parameter('axis info', StringType())
statusbits = Parameter('status bits', StringType()) statusbits = Parameter('status bits', StringType())
target_limits = Parameter('target limits', TupleOf(FloatRange(), FloatRange()), readonly=False) target_min = Limit()
target_max = Limit()
_hw = Positioner() _hw = Positioner()
_scale = 1 # scale for custom units _scale = 1 # scale for custom units
@ -85,16 +54,7 @@ class Axis(FreezeStatus, Drivable):
_history = None _history = None
_check_sensor = False _check_sensor = False
_try_count = 0 _try_count = 0
__freeze_until = 0
def __init__(self, name, logger, opts, srv):
unit = opts.pop('unit', 'deg')
# opts['value.unit'] = unit
try:
# self._scale = self.SCALES[unit] * opts.get('gear', 1)
self._scale = self.SCALES['deg'] * opts.get('gear', 1)
except KeyError as e:
raise ConfigError('unsupported unit: %s' % unit)
super().__init__(name, logger, opts, srv)
def write_gear(self, value): def write_gear(self, value):
self._scale = self.SCALES[self.parameters['value'].datatype.unit] * self.gear self._scale = self.SCALES[self.parameters['value'].datatype.unit] * self.gear
@ -144,7 +104,15 @@ class Axis(FreezeStatus, Drivable):
self._hw.setAxisOutput(self.axis, enable=value, autoDisable=0) self._hw.setAxisOutput(self.axis, enable=value, autoDisable=0)
return value return value
def freeze_status(self, delay, code=BUSY, text='changed target'):
"""freeze status to the given value for the given delay"""
self.__freeze_until = time.time() + delay
self.status = code, text
def read_status(self): def read_status(self):
if time.time() < self.__freeze_until:
return self.status
self.__freeze_until = 0
statusbits = self._hw.getAxisStatus(self.axis) statusbits = self._hw.getAxisStatus(self.axis)
sensor, self.output, moving, attarget, eot_fwd, eot_bwd, sensor_error = statusbits sensor, self.output, moving, attarget, eot_fwd, eot_bwd, sensor_error = statusbits
self.statusbits = ''.join((k for k, v in zip('SOMTFBE', statusbits) if v)) self.statusbits = ''.join((k for k, v in zip('SOMTFBE', statusbits) if v))
@ -214,7 +182,7 @@ class Axis(FreezeStatus, Drivable):
self.log.warn('%r', e) self.log.warn('%r', e)
self._history = [self.value] self._history = [self.value]
self._idle_status = IDLE, '' self._idle_status = IDLE, ''
self.freeze_status(1, BUSY, 'changed target') self.freeze_status(1)
self.setFastPoll(True, 1) self.setFastPoll(True, 1)
return value return value