Skip to content

Commit

Permalink
Add support for loading DCF configuration to remote node (christiansa…
Browse files Browse the repository at this point in the history
…ndberg#427)

Handle PDO-related objects through the associated methods in the PdoBase class when initializing a RemoteNode from an ObjectDictionary with provided values (DCF file usually).  This avoids the locally cached mapping information to get out of sync with the PDO configuration parameters, and thus eliminates the need to read back those same objects.

The PdoBase.read() method must honor DCF-provided values for this purpose.  It previously only respected the OD default values when called with from_od=True.

Co-authored-by: André Colomb <[email protected]>
  • Loading branch information
meifonglow and acolomb authored Jul 4, 2024
1 parent 02ebc0c commit 36c8488
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
15 changes: 11 additions & 4 deletions canopen/node/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,16 +146,23 @@ def load_configuration(self) -> None:
Iterate through all objects in the Object Dictionary and download the
values to the remote node via SDO.
Then, to avoid PDO mapping conflicts, read back (upload) the PDO
configuration via SDO.
To avoid PDO mapping conflicts, PDO-related objects are handled through
the methods :meth:`canopen.pdo.PdoBase.read` and
:meth:`canopen.pdo.PdoBase.save`.
:see-also: :meth:`canopen.pdo.PdoBase.read`
"""
# First apply PDO configuration from object dictionary
self.pdo.read(from_od=True)
self.pdo.save()

# Now apply all other records in object dictionary
for obj in self.object_dictionary.values():
if 0x1400 <= obj.index < 0x1c00:
# Ignore PDO related objects
continue
if isinstance(obj, ODRecord) or isinstance(obj, ODArray):
for subobj in obj.values():
if isinstance(subobj, ODVariable) and subobj.writable and (subobj.value is not None):
self.__load_configuration_helper(subobj.index, subobj.subindex, subobj.name, subobj.value)
elif isinstance(obj, ODVariable) and obj.writable and (obj.value is not None):
self.__load_configuration_helper(obj.index, None, obj.name, obj.value)
self.pdo.read() # reads the new configuration from the driver
13 changes: 11 additions & 2 deletions canopen/pdo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,11 +320,20 @@ def add_callback(self, callback: Callable[[PdoMap], None]) -> None:
self.callbacks.append(callback)

def read(self, from_od=False) -> None:
"""Read PDO configuration for this map using SDO."""
"""Read PDO configuration for this map.
:param from_od:
Read using SDO if False, read from object dictionary if True.
When reading from object dictionary, if DCF populated a value, the
DCF value will be used, otherwise the EDS default will be used instead.
"""

def _raw_from(param):
if from_od:
return param.od.default
if param.od.value is not None:
return param.od.value
else:
return param.od.default
return param.raw

cob_id = _raw_from(self.com_record[1])
Expand Down

0 comments on commit 36c8488

Please sign in to comment.