Skip to content

Commit 8523a68

Browse files
authored
DS402: Minimize side-effects of operation mode switching (ref #244) (#251)
* ds402: Keep target values on operation mode change. As the comment already stated, clearing the target values should possibly happen before switching to the OPERATION ENABLED state, to avoid unexpected movements. So doing that when actually leaving that state is mostly useless. Some legitimate use cases even require switching the operation mode while in OPERATION ENABLED, e.g. switching between Profile Position and Profile Velocity. This change does not allow that, but at the very least will avoid the need to reset target values again. * ds402: Keep power state on operation mode change. Some legitimate use cases require switching the operation mode while in OPERATION ENABLED, e.g. switching between Profile Position and Profile Velocity. If an application or specific controller needs the transition from OPERATION ENABLED to SWITCHED ON during operation mode changes, that should be handled outside this library, and is easy enough to do. On the other hand, having it inside the op_mode setter prevents the above mentioned use-case. * ds402: Improve logging in op_mode setter. Do not generate a log message about the changed operation mode when it actually failed. Use a consistent style for the TypeError message formatting.
1 parent 8e9ccd6 commit 8523a68

File tree

1 file changed

+2
-13
lines changed

1 file changed

+2
-13
lines changed

canopen/profiles/p402.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -361,31 +361,20 @@ def op_mode(self, mode):
361361
try:
362362
if not self.is_op_mode_supported(mode):
363363
raise TypeError(
364-
'Operation mode {0} not suppported on node {1}.'.format(mode, self.id))
365-
366-
start_state = self.state
367-
368-
if self.state == 'OPERATION ENABLED':
369-
self.state = 'SWITCHED ON'
370-
# ensure the node does not move with an old value
371-
self._clear_target_values() # Shouldn't this happen before it's switched on?
372-
364+
'Operation mode {m} not suppported on node {n}.'.format(n=self.id, m=mode))
373365
# operation mode
374366
self.sdo[0x6060].raw = OperationMode.NAME2CODE[mode]
375-
376367
timeout = time.monotonic() + self.TIMEOUT_SWITCH_OP_MODE
377368
while self.op_mode != mode:
378369
if time.monotonic() > timeout:
379370
raise RuntimeError(
380371
"Timeout setting node {0}'s new mode of operation to {1}.".format(
381372
self.id, mode))
373+
logger.info('Set node {n} operation mode to {m}.'.format(n=self.id, m=mode))
382374
except SdoCommunicationError as e:
383375
logger.warning('[SDO communication error] Cause: {0}'.format(str(e)))
384376
except (RuntimeError, ValueError) as e:
385377
logger.warning('{0}'.format(str(e)))
386-
finally:
387-
self.state = start_state # why?
388-
logger.info('Set node {n} operation mode to {m}.'.format(n=self.id, m=mode))
389378

390379
def _clear_target_values(self):
391380
# [target velocity, target position, target torque]

0 commit comments

Comments
 (0)