motor valve using trinamic motor

This valve needs 8 turns to open. As the encoder forgets
the number if turns on power cycle, a home switch is
mounte, which engages during the last turn when closing.
The final close position is determined by closing the valve
with a defined motor current/torque.

+ fix an issue in StateMachine.start: the first cycle
  must be called after the new state is assigned

Change-Id: I34cd05d10d97b043f9e3126310943b74ee727382
Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/28030
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
2022-03-29 16:54:00 +02:00
parent 1ac2f8557c
commit 5a553dbdeb
5 changed files with 293 additions and 23 deletions

View File

@ -177,9 +177,9 @@ class StateMachine:
:return: a delay or None when idle
"""
if self.state is None:
return None
with self._lock:
if self.state is None:
return None
for _ in range(999):
self.now = time.time()
try:
@ -236,7 +236,7 @@ class StateMachine:
pass
delay = self.cycle()
def _start(self, state, first_delay, **kwds):
def _start(self, state, **kwds):
self._restart = None
self._idle_event.clear()
self.last_error = None
@ -245,10 +245,12 @@ class StateMachine:
self._new_state(state)
self.start_time = self.now
self._last_time = self.now
first_delay = self.cycle() # important: call once (e.g. set status to busy)
if self._threaded:
if self._thread is None or not self._thread.is_alive():
# restart thread if dead (may happen when cleanup failed)
self._thread = mkthread(self._run, first_delay)
if first_delay is not None:
self._thread = mkthread(self._run, first_delay)
else:
self.trigger(first_delay)
@ -269,11 +271,9 @@ class StateMachine:
self.last_error = self.stopped
self.cleanup(self) # ignore return state on restart
self.stopped = False
delay = self.cycle()
self._start(state, delay, **kwds)
self._start(state, **kwds)
else:
delay = self.cycle() # important: call once (e.g. set status to busy)
self._start(state, delay, **kwds)
self._start(state, **kwds)
def stop(self):
"""stop machine, go to idle state

View File

@ -736,15 +736,19 @@ class Module(HasAccessibles):
value = self.writeDict.pop(pname, Done)
# in the mean time, a poller or handler might already have done it
if value is not Done:
try:
self.log.debug('initialize parameter %s', pname)
getattr(self, 'write_' + pname)(value)
except SilentError:
pass
except SECoPError as e:
self.log.error(str(e))
except Exception:
self.log.error(formatException())
wfunc = getattr(self, 'write_' + pname, None)
if wfunc is None:
setattr(self, pname, value)
else:
try:
self.log.debug('initialize parameter %s', pname)
wfunc(value)
except SilentError:
pass
except SECoPError as e:
self.log.error(str(e))
except Exception:
self.log.error(formatException())
if started_callback:
started_callback()

View File

@ -72,15 +72,16 @@ class PersistentMixin(HasAccessibles):
persistentdir = os.path.join(generalConfig.logdir, 'persistent')
os.makedirs(persistentdir, exist_ok=True)
self.persistentFile = os.path.join(persistentdir, '%s.%s.json' % (self.DISPATCHER.equipment_id, self.name))
self.initData = {}
self.initData = {} # "factory" settings
for pname in self.parameters:
pobj = self.parameters[pname]
if hasattr(self, 'write_' + pname) and getattr(pobj, 'persistent', 0):
self.initData[pname] = pobj.value
if pobj.persistent == 'auto':
flag = getattr(pobj, 'persistent', 0)
if flag:
if flag == 'auto':
def cb(value, m=self):
m.saveParameters()
self.valueCallbacks[pname].append(cb)
self.initData[pname] = pobj.value
self.writeDict.update(self.loadParameters(write=False))
def loadParameters(self, write=True):