Closed nhayes-me closed 4 months ago
Hi @Rokmonkey,
You can tinker with the code of the BaseNode402 to handle your specific case, it's the only file related to the implementation of the profile DS402 for controlling actuators.
So, here are some assumptions made when writing the code provided by BaseNode402:
Controlword should be configured in one of the RPDO mappings, but fall case to SDO communication, so the object 0x6040 should be present in the DCF or EDS file;
Statusword should be configured in one of the TPDO mappings, but fall case to SDO communication, so the object 0x6041 should be present in the DCF or EDS file;
when defining the operation mode of the node i clear the values for the objects 0x60FF (target velocity), 0x607A (target position) and 0x6071 (target torque) if they are configured.
operation mode is set using the object 0x6060
So, in respect to the hard coded SDO these is it, regarding reading the OptionalObjects you are right, i don't read this section of the DCF/EDS files. If you have the opportunity you can implement this, in your opinion how should this work?? if i have the time i can try to figure how this needs to be implemented but non the less, I don't think your error is related to this.
You should try to see what object is trying to be set and returning that error. That is a generic CAN error 0602 0000hObject does not exist in the object dictionary
, so my advice would be to sniff the CAN Network to figure out what is happening, if you can provide more info would be nice for me to better help you.
Hope this helps ;)
I found the snag, but neglected to show what I found. The problem exists as soon as the node is created.
The kicker of the hardcoding is here in /pdo/ini.py and in the other classes in this file where self.map expects to start at 0x1A00 and go up. If it's not in the EDS file it fails even if CiA402 says they can exist. For some unknown reason the EDS and DCF files for my motors only have the TPDOs that are actually assigned, in my case 0x1a19. I'd modify the code to not try that, but I am fuzzy on where this PDO class gets the expectation of which TPDOs we can access. It must not be from reading the EDS, as they don't show up anywhere.
class PDO(PdoBase):
"""PDO Class for backwards compatibility
:param rpdo: RPDO object holding the Receive PDO mappings
:param tpdo: TPDO object holding the Transmit PDO mappings
"""
def __init__(self, node, rpdo, tpdo):
super(PDO, self).__init__(node)
self.rx = rpdo.map
self.tx = tpdo.map
self.map = {}
# the object 0x1A00 equals to key '1' so we remove 1 from the key
for key, value in self.rx.items():
self.map[0x1A00 + (key - 1)] = value
for key, value in self.tx.items():
self.map[0x1600 + (key - 1)] = value
for reference, the fill stack trace is here:
>>> node.load_configuration()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/pi/.local/lib/python3.7/site-packages/canopen/node/remote.py", line 154, in load_configuration
self.pdo.read() # reads the new configuration from the driver
File "/home/pi/.local/lib/python3.7/site-packages/canopen/pdo/base.py", line 55, in read
pdo_map.read()
File "/home/pi/.local/lib/python3.7/site-packages/canopen/pdo/base.py", line 289, in read
cob_id = self.com_record[1].raw
File "/home/pi/.local/lib/python3.7/site-packages/canopen/variable.py", line 74, in raw
value = self.od.decode_raw(self.data)
File "/home/pi/.local/lib/python3.7/site-packages/canopen/variable.py", line 36, in data
return self.get_data()
File "/home/pi/.local/lib/python3.7/site-packages/canopen/sdo/base.py", line 108, in get_data
return self.sdo_node.upload(self.od.index, self.od.subindex)
File "/home/pi/.local/lib/python3.7/site-packages/canopen/sdo/client.py", line 117, in upload
fp = self.open(index, subindex, buffering=0)
File "/home/pi/.local/lib/python3.7/site-packages/canopen/sdo/client.py", line 197, in open
raw_stream = ReadableStream(self, index, subindex)
File "/home/pi/.local/lib/python3.7/site-packages/canopen/sdo/client.py", line 243, in __init__
response = sdo_client.request_response(request)
File "/home/pi/.local/lib/python3.7/site-packages/canopen/sdo/client.py", line 85, in request_response
return self.read_response()
File "/home/pi/.local/lib/python3.7/site-packages/canopen/sdo/client.py", line 73, in read_response
raise SdoAbortedError(abort_code)
canopen.sdo.exceptions.SdoAbortedError: Code 0x06020000, Object does not exist
Hi @Rokmonkey ,
It must not be from reading the EDS, as they don't show up anywhere.
It seems you are reading the configuration from the driver itself and not from the EDS DCF file, self.pdo.read() # reads the new configuration from the driver
.
And I don't think your problem is related to the TPDO's and RDPO's configuration ....
I think you are having problem when uploading the configuration to the driver return self.sdo_node.upload(self.od.index, self.od.subindex)
, so if you can please check what is happening when this is being fired, and see what is passing in the canbus network.
Double check if you are tying to read the configuration from the driver? (if you do not pass the OD it will try to read from the remote note it's connecting to)
Ahh, perhaps that's it. However, that self.pdo.read() happens automatically when creating a node with BaseNode402, there isn't anything I can do with the library as is. I am passing a DCF/EDS file. Is that a specific object dictionary that needs to be created first?
What is the proper way to read the PDO's from a DCF?
Hi @Rokmonkey,
The pdo.read() from the driver should only happen if you don't provide a ObjectDictionary, if you provide the OD then the code will try to send it to the driver and then read it to make sure the configurations have been set on the driver (configuration of the remote nodes). Try the below code, if this not resolve your issue try to sniff the canbus network to see what is being sent and what is causing the return of the Object does not exist error, namely which Object is returning this.
vnode = VNode("10", "path_to_eds")
self.network.add_node(vnode)
vnode.nmt.state = 'RESET COMMUNICATION' # Reset network
vnode .load_configuration
or, in the signature of the class instance constructor you have the flag to load the configuration (by default is false) def __init__(self, node_id, object_dictionary, load_od=False):
so:
node = BaseNode402("10", "path_to_eds", true)
Hi @Rokmonkey, did you manage to solve the problem? Can I close this ticket?
Closing for inactivity.
I have several motors that have DCF files from the configuration software. For whatever reason, neither the EDS or DCF files are completely filled out as the module demands. For example, the DCF file has TPDO 22 configure and only that, so 0x1A00 is not in the DCF. This throws an error when creating a BaseNode402 object or when trying to read RPDO/TPDO if the node is created with network.add_node().
The error given is as expected: canopen.sdo.exceptions.SdoAbortedError: Code 0x06020000, Object does not exist
I believe this is because certain SDOs are hard-coded in the module for the TPDO/RPDOs instead of reading from the [OptionalObjects] section in the DCF/EDS. I don't know the module well enough to make a pull request and I may also be incorrect in my assumption. Any suggestions on addressing?