diff --git a/canopen/profiles/p402.py b/canopen/profiles/p402.py index bf8b0791..f12e6176 100644 --- a/canopen/profiles/p402.py +++ b/canopen/profiles/p402.py @@ -212,22 +212,31 @@ def __init__(self, node_id, object_dictionary): self.tpdo_pointers = {} # { index: pdo.Map instance } self.rpdo_pointers = {} # { index: pdo.Map instance } - def setup_402_state_machine(self): + def setup_402_state_machine(self, read_pdos=True): """Configure the state machine by searching for a TPDO that has the StatusWord mapped. + :param bool read_pdos: Upload current PDO configuration from node. :raises ValueError: If the the node can't find a Statusword configured in any of the TPDOs. """ - self.nmt.state = 'PRE-OPERATIONAL' # Why is this necessary? - self.setup_pdos() + self.setup_pdos(read_pdos) self._check_controlword_configured() self._check_statusword_configured() - self._check_op_mode_configured() - self.nmt.state = 'OPERATIONAL' - self.state = 'SWITCH ON DISABLED' # Why change state? - def setup_pdos(self): - self.pdo.read() # TPDO and RPDO configurations + def setup_pdos(self, upload=True): + """Find the relevant PDO configuration to handle the state machine. + + :param bool upload: + Retrieve up-to-date configuration via SDO. If False, the node's mappings must + already be configured in the object, matching the drive's settings. + :raises AssertionError: + When the node's NMT state disallows SDOs for reading the PDO configuration. + """ + if upload: + assert self.nmt.state in 'PRE-OPERATIONAL', 'OPERATIONAL' + self.pdo.read() # TPDO and RPDO configurations + else: + self.pdo.subscribe() # Get notified on reception, usually a side-effect of read() self._init_tpdo_values() self._init_rpdo_pointers() diff --git a/doc/profiles.rst b/doc/profiles.rst index 1047c7f9..1ef5ab58 100644 --- a/doc/profiles.rst +++ b/doc/profiles.rst @@ -34,10 +34,13 @@ The current status can be read from the device by reading the register 0x6041, which is called the "Statusword". Changes in state can only be done in the 'OPERATIONAL' state of the NmtMaster -TPDO1 needs to be set up correctly. For this, run the the -`BaseNode402.setup_402_state_machine()` method. Note that this setup -routine will change only TPDO1 and automatically go to the 'OPERATIONAL' state -of the NmtMaster:: +PDOs with the Controlword and Statusword mapped need to be set up correctly, +which is the default configuration of most DS402-compatible drives. To make +them accessible to the state machine implementation, run the the +`BaseNode402.setup_402_state_machine()` method. Note that this setup routine +will read the current PDO configuration by default, causing some SDO traffic. +That works only in the 'OPERATIONAL' or 'PRE-OPERATIONAL' states of the +:class:`NmtMaster`:: # run the setup routine for TPDO1 and it's callback some_node.setup_402_state_machine() @@ -50,21 +53,20 @@ Write Controlword and read Statusword:: # Read the state of the Statusword some_node.sdo[0x6041].raw -During operation the state can change to states which cannot be commanded -by the Controlword, for example a 'FAULT' state. -Therefore the :class:`PowerStateMachine` class (in similarity to the :class:`NmtMaster` -class) automatically monitors state changes of the Statusword which is sent -by TPDO1. The available callback on thet TPDO1 will then extract the -information and mirror the state change in the :attr:`BaseNode402.powerstate_402` -attribute. +During operation the state can change to states which cannot be commanded by the +Controlword, for example a 'FAULT' state. Therefore the :class:`BaseNode402` +class (in similarity to :class:`NmtMaster`) automatically monitors state changes +of the Statusword which is sent by TPDO. The available callback on that TPDO +will then extract the information and mirror the state change in the +:attr:`BaseNode402.state` attribute. Similar to the :class:`NmtMaster` class, the states of the :class:`BaseNode402` -class :attr:`._state` attribute can be read and set (command) by a string:: +class :attr:`.state` attribute can be read and set (command) by a string:: # command a state (an SDO message will be called) - some_node.powerstate_402.state = 'SWITCHED ON' + some_node.state = 'SWITCHED ON' # read the current state - some_node.powerstate_402.state = 'SWITCHED ON' + some_node.state = 'SWITCHED ON' Available states: