From d2e7ce7242f80c054aa911da5b2c7a61c7d1ea8e Mon Sep 17 00:00:00 2001 From: Markus Zolliker Date: Tue, 19 Sep 2023 16:05:52 +0200 Subject: [PATCH] fix simulation + some fixed in sim_uniax Change-Id: Ia8703ed988aa904bb2694339f0d3175b28fcb33e --- cfg/sim_uniax_cfg.py | 2 +- frappy/simulation.py | 9 ++++--- frappy_psi/simdpm.py | 2 +- frappy_psi/uniax.py | 63 ++++++++++++++++++++++++-------------------- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/cfg/sim_uniax_cfg.py b/cfg/sim_uniax_cfg.py index fd856e6..8c35d77 100644 --- a/cfg/sim_uniax_cfg.py +++ b/cfg/sim_uniax_cfg.py @@ -46,7 +46,7 @@ Mod('res', ), value=Param( default=99.0, - datatype={'type': 'double', 'unit': 'Ohm'}, + unit='Ohm', ), ) diff --git a/frappy/simulation.py b/frappy/simulation.py index 6e3de00..65a02c3 100644 --- a/frappy/simulation.py +++ b/frappy/simulation.py @@ -32,12 +32,13 @@ from frappy.modules import Drivable, Module, Parameter, Readable, Writable, Comm class SimBase: def __new__(cls, devname, logger, cfgdict, dispatcher): - extra_params = cfgdict.pop('extra_params', '') or cfgdict.pop('.extra_params', '') + extra_params = cfgdict.pop('extra_params', '')['value'] + if isinstance(extra_params, str): + extra_params = [v.strip() for v in extra_params.split(',')] attrs = {} if extra_params: - for k in extra_params['value'].split(','): - k = k.strip() - attrs[k] = Parameter(f'extra_param: {k.strip()}', + for k in extra_params: + attrs[k] = Parameter(f'extra_param: {k}', datatype=FloatRange(), default=0.0) diff --git a/frappy_psi/simdpm.py b/frappy_psi/simdpm.py index de00edb..97e9fa9 100644 --- a/frappy_psi/simdpm.py +++ b/frappy_psi/simdpm.py @@ -38,7 +38,7 @@ class DPM3(Readable): _pos = 0 def read_value(self): - mot = self._motor + mot = self.motor d = self.friction * self.slope self._pos = clamp(self._pos, mot.value - d, mot.value + d) f = (mot.value - self._pos) / self.slope diff --git a/frappy_psi/uniax.py b/frappy_psi/uniax.py index 64a7e51..7c66298 100644 --- a/frappy_psi/uniax.py +++ b/frappy_psi/uniax.py @@ -26,9 +26,9 @@ import math from frappy.core import Drivable, Parameter, FloatRange, Done, \ Attached, Command, PersistentMixin, PersistentParam, BoolType from frappy.errors import BadValueError, SECoPError -from frappy.lib.statemachine import Retry, StateMachine, Restart +from frappy.lib.statemachine import Retry, StateMachine, Stop -# TODO: fix with new state machine! +# TODO: to be tested, or better migrated to new state machine! class Error(SECoPError): @@ -46,11 +46,11 @@ class Uniax(PersistentMixin, Drivable): pid_i = PersistentParam('integral', FloatRange(), readonly=False, default=0.5, persistent='auto') filter_interval = Parameter('filter time', FloatRange(0, 60, unit='s'), readonly=False, default=5) current_step = Parameter('', FloatRange(unit='deg'), default=0) - force_offset = PersistentParam('transducer offset', FloatRange(unit='N'), readonly=False, default=0, - initwrite=True, persistent='auto') + force_offset = PersistentParam('transducer offset', FloatRange(unit='N'), readonly=False, value=0, + persistent='auto') hysteresis = PersistentParam('force hysteresis', FloatRange(0, 190, unit='N'), readonly=False, default=5, persistent='auto') - adjusting = Parameter('', BoolType(), readonly=False, default=False, initwrite=True) + adjusting = Parameter('', BoolType(), readonly=False, value=False) adjusting_current = PersistentParam('current when adjusting force', FloatRange(0, 2.8, unit='A'), readonly=False, default=0.5, persistent='auto') safe_step = PersistentParam('max. motor step when adjusting force', FloatRange(0, unit='deg'), readonly=False, @@ -116,11 +116,15 @@ class Uniax(PersistentMixin, Drivable): def motor_busy(self): mot = self.motor if mot.isBusy(): - if mot.target != self._mot_target: + if self._mot_target is not None and mot.target != self._mot_target: raise Error('control stopped - motor moved directly') return True return False + def motor_stop(self): + self.motor.stop() + self._mot_target = None + def read_value(self): try: self._force = force = self.transducer.read_value() @@ -142,7 +146,7 @@ class Uniax(PersistentMixin, Drivable): force = self._sum / self._cnt self.reset_filter(now) if abs(force) > self.limit + self.hysteresis: - self.motor.stop() + self.motor_stop() self.status = 'ERROR', 'above max limit' self.log.error(self.status[1]) self.read_target() @@ -188,8 +192,8 @@ class Uniax(PersistentMixin, Drivable): def cleanup(self, state): """in case of error, set error status""" - if state.stopped: # stop or restart - if state.stopped is Restart: + if state.next_task: # stop or restart + if not isinstance(state.next_task, Stop): return self.status = 'IDLE', 'stopped' self.log.warning('stopped') @@ -200,7 +204,7 @@ class Uniax(PersistentMixin, Drivable): else: self.log.error('%r raised in state %r', str(state.last_error), state.status_string) self.read_target() # make target invalid - self.motor.stop() + self.motor_stop() self.write_adjusting(False) def reset_progress(self, state): @@ -234,7 +238,7 @@ class Uniax(PersistentMixin, Drivable): state.direction = math.copysign(1, self.target - self.value) state.pid_fact = 1 if self.motor_busy(): - return Retry() + return Retry self.value = self._force force_step = self.target - self.value if abs(force_step) < self.tolerance: @@ -255,6 +259,7 @@ class Uniax(PersistentMixin, Drivable): self.status = 'BUSY', 'adjusting force' elif not self.check_progress(state): if abs(self.value) < self.hysteresis: + motor_dif = abs(self.motor.value - state.prev_pos) if motor_dif > self.motor_play: self.log.warning('adjusting failed - try to find zero pos') self.set_zero_pos(self.target, None) @@ -265,15 +270,15 @@ class Uniax(PersistentMixin, Drivable): self.log.warning('no substantial progress since %d sec', self.timeout) self.status = 'IDLE', 'adjusting timeout' self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * state.pid_fact) - return Retry() + return Retry def within_tolerance(self, state): """within tolerance""" if state.init: self.status = 'IDLE', 'within tolerance' - return Retry() + return Retry if self.motor_busy(): - return Retry() + return Retry force_step = self.target - self.value if abs(force_step) < self.tolerance * 0.5: self.current_step = 0 @@ -282,16 +287,16 @@ class Uniax(PersistentMixin, Drivable): self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * 0.1) if abs(force_step) > self.tolerance: return self.out_of_tolerance - return Retry() + return Retry def out_of_tolerance(self, state): """out of tolerance""" if state.init: self.status = 'WARN', 'out of tolerance' state.in_since = 0 - return Retry() + return Retry if self.motor_busy(): - return Retry() + return Retry force_step = self.target - self._force if abs(force_step) < self.tolerance: if state.in_since == 0: @@ -299,10 +304,10 @@ class Uniax(PersistentMixin, Drivable): if state.now > state.in_since + 10: return self.within_tolerance if abs(force_step) < self.tolerance * 0.5: - return Retry() + return Retry self.check_progress(state) self.drive_relative(force_step * self.slope * self.pid_i * min(1, state.delta()) * 0.1) - return Retry() + return Retry def find(self, state): """find active (engaged) range""" @@ -315,7 +320,7 @@ class Uniax(PersistentMixin, Drivable): if abs_force > self.hysteresis or abs_force > self.target * direction: if self.motor_busy(): self.log.info('motor stopped - substantial force detected: %g', self.value) - self.motor.stop() + self.motor_stop() elif state.prev_direction == 0: return self.adjust if abs_force > self.hysteresis: @@ -326,9 +331,9 @@ class Uniax(PersistentMixin, Drivable): return self.free if self.motor_busy(): if direction == -state.prev_direction: # target direction changed - self.motor.stop() + self.motor_stop() state.init_find = True # restart find - return Retry() + return Retry zero_pos = self.zero_pos(self.target) if state.prev_direction: # find already started if abs(self.motor.target - self.motor.value) > self.motor.tolerance: @@ -336,7 +341,7 @@ class Uniax(PersistentMixin, Drivable): self.write_adjusting(True) self.log.info('one step to %g', self.motor.value + self.safe_step) self.drive_relative(direction * self.safe_step) - return Retry() + return Retry else: state.prev_direction = math.copysign(1, self.target) side_name = 'negative' if direction == -1 else 'positive' @@ -347,14 +352,14 @@ class Uniax(PersistentMixin, Drivable): self.write_adjusting(False) self.log.info('change side to %g', zero_pos) self.drive_relative(zero_pos - self.motor.value) - return Retry() + return Retry # we are already at or beyond zero_pos return self.adjust self.write_adjusting(False) self.status = 'BUSY', 'find %s side' % side_name self.log.info('one turn to %g', self.motor.value + direction * 360) self.drive_relative(direction * 360) - return Retry() + return Retry def free(self, state): """free from high force at other end""" @@ -362,7 +367,7 @@ class Uniax(PersistentMixin, Drivable): state.free_way = None self.reset_progress(state) if self.motor_busy(): - return Retry() + return Retry self.value = self._force if abs(self.value) > abs(state.force_before_free) + self.hysteresis: raise Error('force increase while freeing') @@ -377,7 +382,7 @@ class Uniax(PersistentMixin, Drivable): raise Error('freeing failed') state.free_way += self.safe_step self.drive_relative(direction * self.safe_step) - return Retry() + return Retry def write_target(self, target): if abs(target) > self.limit: @@ -399,7 +404,7 @@ class Uniax(PersistentMixin, Drivable): return Done def read_target(self): - if self._state.state is None: + if self._state.statefunc is None: if self.status[1]: raise Error(self.status[1]) raise Error('inactive') @@ -409,7 +414,7 @@ class Uniax(PersistentMixin, Drivable): def stop(self): if self.motor.isBusy(): self.log.info('stop motor') - self.motor.stop() + self.motor_stop() self.status = 'IDLE', 'stopped' self._state.stop()