bnjmnp / pysoem

Cython wrapper for the Simple Open EtherCAT Master Library
MIT License
95 stars 36 forks source link

config_map ConfigMapError because subindex 0 does not exist #105

Closed tomhira closed 1 year ago

tomhira commented 1 year ago

Hello I have this error, SdoError(1, **, , ****, 'Unsupported access to an object'), because my device's PDO Mapping Object does not support subindex 0. Instead, it starts with 1. How can workaround this? (By the way, I have other slave that have subindex starts with 0. that works fine.)

bnjmnp commented 1 year ago

Sorry, I don't have a clue how you could get around this. Maybe there is a firmware update for this device? Sounds to me like it violates the EtherCAT conformance. Did you try operate this device with another EtherCAT master system? You could also go through the SOEM issue list, maybe something similar has been discussed there. But this SDO abort does not occur in your config function, right?

tomhira commented 1 year ago

Hello Thanks for the response. I mean I have a device in PDO Mapping 0x1600 and 0x1A00, no subindex 0 whether it violates the spec or not. I would like to go around by specifying the entry number for the index because I have the specification of the entries. Could I do do this?

tomhira commented 1 year ago

Or at least make this error not abort and read the specified number of subindex entries?

tomhira commented 1 year ago

Sorry, I found out actually subindex 0 exists, but for some reason 'Unsupported access to an object' is given when config_map is called. Does someone have a clue as to why it issues a SDO exception?

tomhira commented 1 year ago

Additionally, I appreciate if there is way to debug why this is becoming error.

tomhira commented 1 year ago

Hello. Using Wireshark, I looked the transaction sequence. It found the first sending of Initiate Upload request is responded by Abort Transfer, but the resending request to the same is returned normally. How can I avoid program to stop running by this error?

bnjmnp commented 1 year ago

If only the first read of this object creates an error, you might try to access this object before calling config_map() and catching the Abort Transfer, like this:

try:
    device.sdo_read(0x...)
except pysoem.SdoError:
    pass

master.config_map()

Modified: changed config_init() to changed config_map()

tomhira commented 1 year ago

Thanks for reply. I tried. It made error, but the first access of the write of config_map() creates the abort error. I do not why. Could I go around it?

tomhira commented 1 year ago

This seems to abort in the middle of the function without finishing it. try: master.config_map() except pysoem.ConfigMapError: pass

tomhira commented 1 year ago

Hi, bnjmnp. Could I access by sdo write the mapped address of 0x7000,0x7004,0x7005(so are my RxPDO default mapping)? If config_map is successful, where are the mapped addresses I can check?

tomhira commented 1 year ago

Hi, bnjmnp. I need your help. code: self._master.slaves[0].sdo_write(index=0x7005, subindex=1, data=bytes(0x000003E8), ca=False) produce in Wireshare as This seems the data is 0 and 3E8 data is set to size only. What is wrong with the code? EtherCAT frame header .... .000 1000 1100 = Length: 0x08c .... 0... .... .... = Reserved: Valid (0x0) 0001 .... .... .... = Type: EtherCAT command (0x1) EtherCAT datagram(s): 'FPWR': Len: 128, Adp 0x1001, Ado 0x1000, Wc 1 EtherCAT datagram: Cmd: 'FPWR' (5), Len: 128, Adp 0x1001, Ado 0x1000, Cnt 1 Header EtherCAT Mailbox Protocol:CoE SDO Req : 'Initiate Download' (1) Idx=0x7005 Sub=1 Header Length: 122 Address: 0x0000 .... ..00 = Priority: 0 Type: CoE (CANopen over EtherCAT) (3) Counter: 1 CoE Number: 0 Type: SDO Req (2) SDO Req : 'Initiate Download' (1) Idx=0x7005 Sub=1 Initiate Download: 0x21 .... ...1 = Size Ind.: Set .... ..0. = Expedited: Not set .... .0.. = Bytes: Not set .... 0... = Bytes: Not set ...0 .... = Access: Legacy Index: 0x7005 SubIndex: 0x01 Length: 0x000003e8 Data: 000000000000000000000000000000000000000000000000000000000000000000000000… Working Cnt: 1

bnjmnp commented 1 year ago
bytes(0x000003E8)

Creates a 1000 (hex 3E8) elements long array of bytes filled with zeros. Maybe this is not what you want to write to 0x7001:01.

I guess object 0x7001 entry 1 is a 32 bit unsigned integer, and you want to write the hexadecimal value 0x000003E8 to it.

This could be done by something like that.

self._master.slaves[0].sdo_write(index=0x7005, subindex=1, data=(0x000003E8).to_bytes(4, byteorder='little', signed=False), ca=False)

Or that

self._master.slaves[0].sdo_write(index=0x7005, subindex=1, data=bytes(ctypes.c_uint32(0x000003E8)), ca=False)

I wrote a few things together in the PySOEM documentation: https://pysoem.readthedocs.io/en/latest/coe_objects.html#reading-and-writing-coe-objects about this topic.

bnjmnp commented 1 year ago

Note that actuators need to be in operational state in order to be able to change the state of their outputs.

Could you share the wireshark log of this incident:

Sorry, I found out actually subindex 0 exists, but for some reason 'Unsupported access to an object' is given when config_map is called. Does someone have a clue as to why it issues a SDO exception?

tomhira commented 1 year ago

Hi, bnjmnp. Thanks for the instruction for sdo_write. I realized my mistake. For the log, I would like to share by email or other communication tool. Do you have the email address or other tool for it? Sorry for the inconvinience.

bnjmnp commented 1 year ago

You can attach the log directly to a comment. Just keep it small I would say. Do you only have this device that doesn't seem to work with PySOEM, or do you have other EtherCAT slave devices at hand?

tomhira commented 1 year ago

Hello I have just one other. that is ok. I attach the log. please check. This is implemented version of try: print("HERE2")
io_map_size = self._master.config_map() print('IOMap-Size: {}'.format(io_map_size)) except pysoem.ConfigMapError: pass but io_map_size does not come.

tomhira commented 1 year ago

Hello bnjmnp Could you find anything?

bnjmnp commented 1 year ago

I just noticed that it is the SDO read with "complete access" that fails for 0x1600, the normal one goes through. I remember there was a similar issue #99 where this was solved by a firmware update of the device. The pysoem workaround is not there at the moment. Maybe you also have a firmware update for your device?

tomhira commented 1 year ago

Hello, bnjmnp. Thanks for the help! I will check.

tomhira commented 1 year ago

Hello, bnjmnp. I see how complete access fails. It seems the device update is not coming soon. The mapping seems fine, so is there way to complete the function by demoting this error to info?

bnjmnp commented 1 year ago

This error is handled in the SOEM C code, so there is no way to let it pass in PySOEM code. I'll try to implement a way to "disabling complete access" in the next days.

tomhira commented 1 year ago

Hello bnjmnp. Thanks a lot! Best regards, Tom

bnjmnp commented 1 year ago

I got something for you to try out. I pushed it to the develop branch and you can test it by installing pysoem form TestPyPI instead of the regular PyPI using pip install -i https://test.pypi.org/simple/ pysoem.

If it works fine, I will later merge the develop branch into the main branch and upload a release to PyPI.

The new version introduces function _disable_complete_access(). You ether call it prior tho the call of config_map():

    master.slaves[<pos_of_faulty_device>]._disable_complete_access()
    master.config_map()

or you do that inside the config_func.

tomhira commented 1 year ago

Hello bnjmnp. Thanks! I try, and let you know. Best regards, Tom

tomhira commented 1 year ago

Hello bnjmnp. It worked without abort. io_map_size = self._master.config_map() returned the value normally. Thanks very much for your help! Tom

bnjmnp commented 1 year ago

Great. The _disable_complete_access() function should now also be available in regular installs via pip install pysoem.