bnjmnp / pysoem

Cython wrapper for the Simple Open EtherCAT Master Library
MIT License
96 stars 37 forks source link

How to override default write to 0x1c13 on device init? #53

Closed AKAMEDIASYSTEM closed 6 months ago

AKAMEDIASYSTEM commented 2 years ago

Hi, I'm having good luck using this library to talk to a few EK1100 and EL4102 units - thank you very much for making such readable and accessible software!

I'm basically adapting the basic_example.py script to my needs and this works great with the EL4102 (a 2-channel analog output device). I don't need to do anything in a setup function, I can just send output values every pdo cycle.

However, I'm having trouble adding an 8-channel device (EL4008) from the same family to this setup. When the script gets to lf._master.config_map() it fails with the error:

BasicExample(sys.argv[1]).run()
  File "/home/pi/akatesting/ethercatscratch/aka_basic_example.py", line 164, in run
    self._master.config_map()
  File "pysoem/pysoem.pyx", line 228, in pysoem.pysoem.CdefMaster.config_map
pysoem.pysoem.ConfigMapError: [SdoError(3, 7187, 1, 101253137, 'Subindex does not exist')]

...from what I understand of 'SdoError' structure here, this means that in the normal course of config_map the master tries to write to slave 3 (the EL4008, in my setup - if I switch the installation order the "3" changes accordingly) at the address 0x1c13, which would definitely fail with "Subindex does not exist" because that is true for EL4008.

I'm confused by this because in other examples online (the very helpful https://github.com/ngblume/ethercat-pysoem/blob/master/separate_thread/separate_thread.py for example) there is no indication of EL4008 needing special treatment on startup. Have others had luck with recent builds of SOEM and pySOEM nd the EL4008? I am wondering if perhaps the underlying SOEM library has changed how it initializes devices?

Many thanks for any help you can provide - for what it's worth my script is here: https://github.com/AKAMEDIASYSTEM/ethercatscratch/blob/master/aka_basic_example.py

bnjmnp commented 2 years ago

Hi. I don't have an idea why this error is raised, for now. There was no change to config_map I can think of. Did you also try not to provide a setup function at all?

BTW: I work on documenting pysoem on readthedocs. Not everything is covered by now but the SDOError class can be found here: https://pysoem.readthedocs.io/en/latest/exceptions.html#pysoem.SdoError

AKAMEDIASYSTEM commented 2 years ago

Thanks for the quick response! I have read the documentation for SdoError, but momentarily forgot that would be the best place to reference its returned value order when I wrote the issue yesterday - sorry for not pointing to the much-clearer source in the ReadTheDocs!

Even with all config_func set to None, unfortunately I still get the same SdoError mentioned in the original issue:

        self._expected_slave_layout = {0: SlaveSet('EK1100', self.EK1100_PRODUCT_CODE, None),
                                       1: SlaveSet('EL4102', self.EL4102_PRODUCT_CODE, None),
                                       2: SlaveSet('EL4008', self.EL4008_PRODUCT_CODE, None)
                                        }

It's super-confusing to me in part because other seem to have gotten this module working without any need for config_func or other setups...I will try factory-resetting all modules at init and seeing if that gets me anywhere (and will of course update here if I learn anything).

Thanks for your help!

AKA

AKAMEDIASYSTEM commented 2 years ago

...just to add more info to this, I built the most recent version of SOEM (the superseding C library) and am able to run linux/simpletest just fine, which I was surprised by!

Now I'm looking back at changes to pysoem dating back to March 2020, as that is when ngblume's ethercat-pysoem library last updated the script that seems to have working code talking to an EL4008. I may try to set up a venv and install pysoem-0.1.1 and see if that works?

FWIW I have 5 of EL4008 and each one responds the same, so I'm thinking it is unlikely to be a configuration error on the device; however, I find TwinCAT really difficult and confusing so I have not yet tried to talk tot eh units through that program...

bnjmnp commented 2 years ago

Right, you could try pysoem 0.1.1. (pip install pysoem==0.1.1) and see if it works there, not much has change.

AKAMEDIASYSTEM commented 2 years ago

Thanks for the reply - still no luck with pysoem==0.1.1, which is confusing given the success of ngblume's separate_thread.py script back in March 2020 or so. Next up I will go full time capsule ;-) using pysoem==0.1.1 and trying to use the SOEM version from around the same time (as far as I can tell, it's this March 3 snapshot) I wish I was better at reading C, bceause I'm determined to get this all working...

Thanks again for the help!

AKA

AKAMEDIASYSTEM commented 2 years ago

Just an update, I realized that the "subindex does not exist" error isn't a show-stopper for me, since I'm only writing analog output values. So to get around this, rather than change the behavior of the underlying SOEM library I instead altered the error handling behavior during the config_map() call here and here. The change I made is to simply log the errorList and pass instead of raise.

Now, I see the errors in logging but am able to continue starting up, and all slaves are able to enter operational state and respond to pdo output commands.

I'm new to EtherCAT (obviously) so if this is a huge red flag, and there's a better way to proceed, please let me know! (And thank you for your help in figuring this out.)

AKA

bnjmnp commented 2 years ago

I think it is okay to do that.

If you are not interested in the return value of config_map() you could also handle the exception like this in your application code.

try:
    self._master.config_map()
except pysoem.ConfigMapError as ex:
    if len(ex.error_list) == 1 and ex.error_list[0] == SdoError(3, 7187, 1, 101253137, 'Subindex does not exist'):
        # just the expected SDO error is in the list
        pass
    else:
        # more errors than expected 
        raise pysoem.ConfigMapError(ex.error_list) from ex

Thus other errors are not dropped.

I'm still curios why pysoem is trying to access 0x1C13:01... I think in the next weeks I will investigate that further and would be glad if you could try out a few tings for me.

bnjmnp commented 2 years ago

I created a branch off the current pysoem release where I updated the underlying SOEM sources to the latest code available on GitHub. In the best case this will already bring the solution. To build and install pysoem directly from GitHub use: python -m pip install git+https://github.com/bnjmnp/pysoem.git@new_soem. With the @new_pysoem you will install the mentioned branch where I updated SOEM. Just tell me if you have issues with the install.

AKAMEDIASYSTEM commented 2 years ago

Thank you! I will try this in the next few days and report back here.

bnjmnp commented 6 months ago

Closed due to inactivity of the OP. Please reopen the ticket if needed.