persistent module fixed

This commit is contained in:
2021-06-08 07:39:46 +02:00
parent 246ab99e12
commit 25b8780b11
5 changed files with 110 additions and 54 deletions

View File

@ -27,7 +27,7 @@ import struct
from math import log10
from secop.core import BoolType, Command, EnumType, FloatRange, IntRange, \
HasIodev, Parameter, Property, Drivable, TupleOf, Done
HasIodev, Parameter, Property, Drivable, TupleOf, Done, PersistentMixin, PersistentParam
from secop.bytesio import BytesIO
from secop.errors import CommunicationFailedError, HardwareError, BadValueError, IsBusyError
@ -53,16 +53,19 @@ CURRENT_SCALE = 2.8/250
ENCODER_RESOLUTION = 0.4 # 365 / 1024, rounded up
class HwParam(Parameter):
class HwParam(PersistentParam):
adr = Property('parameter address', IntRange(0, 255), export=False)
scale = Property('parameter address', FloatRange(), export=False)
scale = Property('scale factor (physical value / unit)', FloatRange(), export=False)
def __init__(self, description, datatype, adr, scale=1, poll=True, persistent=False, **kwds):
def __init__(self, description, datatype, adr, scale=1, poll=True,
readonly=True, persistent=None, **kwds):
"""hardware parameter"""
if isinstance(datatype, FloatRange) and not kwds.get('fmtstr'):
datatype.fmtstr = '%%.%df' % max(0, 1 - int(log10(scale)))
if persistent is None:
persistent = not readonly
if isinstance(datatype, FloatRange) and datatype.fmtstr == '%g':
datatype.fmtstr = '%%.%df' % max(0, 1 - int(log10(scale) + 0.01))
super().__init__(description, datatype, poll=poll, adr=adr, scale=scale,
persistent=persistent, **kwds)
persistent=persistent, readonly=readonly, **kwds)
def copy(self):
res = HwParam(self.description, self.datatype.copy(), self.adr)
@ -71,50 +74,54 @@ class HwParam(Parameter):
return res
class Motor(HasIodev, Drivable):
class Motor(PersistentMixin, HasIodev, Drivable):
address = Property('module address', IntRange(0, 255), default=1)
# limit_pin_mask = Property('input pin mask for lower/upper limit switch',
# TupleOf(IntRange(0, 15), IntRange(0, 15)),
# default=(8, 0))
value = Parameter('motor position', FloatRange(unit='deg'))
zero = Parameter('zero point', FloatRange(unit='$'), readonly=False, default=0, persistent=True)
encoder = HwParam('encoder reading', FloatRange(unit='$'),
value = Parameter('motor position', FloatRange(unit='deg', fmtstr='%.3f'))
zero = PersistentParam('zero point', FloatRange(unit='$'), readonly=False, default=0)
encoder = HwParam('encoder reading', FloatRange(unit='$', fmtstr='%.1f'),
209, ANGLE_SCALE, readonly=True, initwrite=False, persistent=True)
steppos = HwParam('position from motor steps', FloatRange(unit='$'),
1, ANGLE_SCALE, readonly=True, initwrite=False)
target = Parameter('_', FloatRange(unit='$'), default=0)
movelimit = Parameter('max. angle to drive in one go', FloatRange(unit='$'),
readonly=False, default=360, group='more', persistent=True)
readonly=False, default=360, group='more')
tolerance = Parameter('positioning tolerance', FloatRange(unit='$'),
readonly=False, default=0.9)
encoder_tolerance = HwParam('the allowed deviation between steppos and encoder\n\nmust be > tolerance',
FloatRange(0, 360., unit='$'),
212, ANGLE_SCALE, readonly=False, group='more', persistent=True)
212, ANGLE_SCALE, readonly=False, group='more')
speed = HwParam('max. speed', FloatRange(0, MAX_SPEED, unit='$/sec'),
4, SPEED_SCALE, readonly=False, group='more', persistent=True)
4, SPEED_SCALE, readonly=False, group='more')
minspeed = HwParam('min. speed', FloatRange(0, MAX_SPEED, unit='$/sec'),
130, SPEED_SCALE, readonly=False, default=SPEED_SCALE, group='motorparam')
currentspeed = HwParam('current speed', FloatRange(-MAX_SPEED, MAX_SPEED, unit='$/sec'),
3, SPEED_SCALE, readonly=True, group='motorparam')
maxcurrent = HwParam('_', FloatRange(0, 2.8, unit='A'),
6, CURRENT_SCALE, readonly=False, group='motorparam', persistent=True)
6, CURRENT_SCALE, readonly=False, group='motorparam')
standby_current = HwParam('_', FloatRange(0, 2.8, unit='A'),
7, CURRENT_SCALE, readonly=False, group='motorparam')
acceleration = HwParam('_', FloatRange(4.6 * ACCEL_SCALE, MAX_ACCEL, unit='deg/s^2'),
5, ACCEL_SCALE, readonly=False, group='motorparam', persistent=True)
5, ACCEL_SCALE, readonly=False, group='motorparam')
target_reached = HwParam('_', BoolType(), 8, group='hwstatus')
move_status = HwParam('_', IntRange(0, 3),
207, readonly=True, persistent=False, group='hwstatus')
207, readonly=True, group='hwstatus')
error_bits = HwParam('_', IntRange(0, 255),
208, readonly=True, persistent=False, group='hwstatus')
208, readonly=True, group='hwstatus')
# the doc says msec, but I believe the scale is 10 msec
free_wheeling = HwParam('_', FloatRange(0, 60., unit='sec'),
204, 0.001, readonly=False, group='motorparam', persistent=True)
204, 0.01, default=0.1, readonly=False, group='motorparam')
power_down_delay = HwParam('_', FloatRange(0, 60., unit='sec'),
214, 0.01, default=0.1, readonly=False, group='motorparam')
baudrate = Parameter('_', EnumType({'%d' % v: i for i, v in enumerate(BAUDRATES)}),
readonly=False, default=0, poll=True, visibility=3, group='more')
pollinterval = Parameter(group='more', persistent=True)
pollinterval = Parameter(group='more')
iodevClass = BytesIO
fast_pollfactor = 0.001 # poll as fast as possible when busy
@ -216,20 +223,13 @@ class Motor(HasIodev, Drivable):
initialized = self.comm(GET_GLOB_PAR, 255, bank=2)
if initialized: # no power loss
self.saveParameters()
if any((v==0 for v in self.persistentData.values())):
print('SAVED', self.persistentData)
print('SAVED', self.persistentData)
else: # just powered up
# get persistent values
writeDict = self.loadParameters()
# self.encoder now contains the last known (persistent) value
self.log.info('set to previous saved values %r', writeDict)
for pname, value in writeDict.items():
try:
getattr(self, 'write_' + pname)(value)
except Exception as e:
self.log.warning('can not write %r to %r (%r)' % (value, pname, e))
# self.encoder now contains the last known (persistent) value
self.fix_encoder(encoder)
value = self.encoder - self.zero
self.comm(SET_GLOB_PAR, 255, 1, bank=2) # set initialized flag
self._started = 0
self._need_reset = True
@ -352,6 +352,12 @@ class Motor(HasIodev, Drivable):
def write_free_wheeling(self, value):
return self.set('free_wheeling', value)
def read_power_down_delay(self):
return self.get('power_down_delay')
def write_power_down_delay(self, value):
return self.set('power_down_delay', value)
def read_move_status(self):
return self.get('move_status')
@ -382,7 +388,7 @@ class Motor(HasIodev, Drivable):
return
self.set('steppos', self.encoder - self.zero, check=False)
self.comm(MOVE, 0, (self.encoder - self.zero) / ANGLE_SCALE)
time.sleep(0.01)
time.sleep(0.1)
if itry > 5:
tol = self.tolerance
self.status = self.Status.ERROR, 'reset failed'