sveinse / canopen-asyncio

CANopen for Python
http://canopen.readthedocs.io/
MIT License
7 stars 2 forks source link

await node.tpdo.aread() Error:Timeout: No SDO response received: Even response is listed on candump #8

Open GIT1RWM2AR opened 1 year ago

GIT1RWM2AR commented 1 year ago

Hello to everyone, hello Svein,

I have tried to adapt your example to work with my configuration. I ran into a timeout-error even the motor-node is responding. Setting the RESPONSE_TIMEOUT = 1.5 seconds is no workaround. Any help will be appreciated.
Thank you in advance.

First I show the error, than the $candump -td slcan0, than the modified Phyton-Code: (marked error-lined with: -----> ) At the end I add some code, where I tried to use an USB-PCAN-Dongle from company PEAK; but I ran into the same SDO-Timeout-Error

The last executed program-lines:

async def aread_response(self):
    try:
        response = await asyncio.wait_for(
            self.aresponses.get(), timeout=self.RESPONSE_TIMEOUT)
    except asyncio.TimeoutError:
        raise SdoCommunicationError("No SDO response received")

The debugger-output:

File "/usr/lib/python3.10/asyncio/queues.py", line 159, in get await getter asyncio.exceptions.CancelledError During handling of the above exception, another exception occurred:

File "/usr/lib/python3.10/asyncio/tasks.py", line 456, in wait_for return fut.result()

asyncio.exceptions.CancelledError The above exception was the direct cause of the following exception: File "/home/ar/.local/lib/python3.10/site-packages/canopen/sdo/client.py", line 115, in aread_response response = await asyncio.wait_for( File "/usr/lib/python3.10/asyncio/tasks.py", line 458, in wait_for raise exceptions.TimeoutError() from exc asyncio.exceptions.TimeoutError During handling of the above exception, another exception occurred: File "/home/ar/Schreibtisch/WING-Test-3/CANopen-Async-IO-2023-05-01.py", line 96, in main() File "/home/ar/Schreibtisch/WING-Test-3/CANopen-Async-IO-2023-05-01.py", line 93, in main asyncio.run(amain()) File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete return future.result() File "/home/ar/Schreibtisch/WING-Test-3/CANopen-Async-IO-2023-05-01.py", line 86, in amain await asyncio.gather( File "/home/ar/Schreibtisch/WING-Test-3/CANopen-Async-IO-2023-05-01.py", line 21, in do_loop await node.tpdo.aread() File "/home/ar/.local/lib/python3.10/site-packages/canopen/pdo/base.py", line 67, in aread await pdo_map.aread(from_od=from_od) File "/home/ar/.local/lib/python3.10/site-packages/canopen/pdo/base.py", line 430, in aread value = await var.aget_raw() File "/home/ar/.local/lib/python3.10/site-packages/canopen/variable.py", line 91, in aget_raw return self._get_raw(await self.aget_data()) File "/home/ar/.local/lib/python3.10/site-packages/canopen/sdo/base.py", line 162, in aget_data return await self.sdo_node.aupload(self.od.index, self.od.subindex) File "/home/ar/.local/lib/python3.10/site-packages/canopen/sdo/client.py", line 219, in aupload async with await self.aopen(index, subindex, buffering=0) as fp: File "/home/ar/.local/lib/python3.10/site-packages/canopen/sdo/client.py", line 402, in aopen raw_stream = await AReadableStream.open(self, index, subindex) File "/home/ar/.local/lib/python3.10/site-packages/canopen/sdo/client.py", line 550, in open response = await sdo_client.arequest_response(request) File "/home/ar/.local/lib/python3.10/site-packages/canopen/sdo/client.py", line 151, in arequest_response return await self.aread_response() File "/home/ar/.local/lib/python3.10/site-packages/canopen/sdo/client.py", line 118, in aread_response raise SdoCommunicationError("No SDO response received")

canopen.sdo.exceptions.SdoCommunicationError: No SDO response received


The candump-output: --> ~4ms SDO-Responce-Time: ?? Why is the SDO responce is not received ??

(000.046334) slcan0 70A [1] 7F (002.848479) slcan0 607 [8] 40 00 18 01 00 00 00 00 Node:0x07: SDO: 0x1800.01 Request (000.003872) slcan0 587 [8] 43 00 18 01 87 01 00 00 Node:0x07: SDO: 0x1800.01 Responce: 3.87ms after Request (000.101092) slcan0 707 [1] 7F (000.004045) slcan0 60A [8] 40 00 18 01 00 00 00 00 Node:0x0A: SDO: 0x1800.01 Request (000.003953) slcan0 58A [8] 43 00 18 01 8A 01 00 00 Node:0x0a: SDO: 0x1800.01 Responce: 3.95ms after Request (000.038419) slcan0 70A [1] 7F (001.351532) slcan0 607 [8] 80 00 00 00 00 00 04 05 (001.602012) slcan0 707 [1] 7F


Your example: Adapted to my physical hardware-setting: Node: 7 and Node 0x0A

Python-Source-Code:

import asyncio
import logging
import can
import canopen

# Set logging output
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)

async def do_loop(network: canopen.Network, nodeid):

    # Create the node object and load the OD
    #node: canopen.RemoteNode = network.add_node(nodeid, 'eds/e35.eds')
    node: canopen.RemoteNode = network.add_node(nodeid, '/home/ar/Schreibtisch/RWM_RC_2023_Test/CANopenEDS/ObjDict_DS402_LA1000.eds')

    node.sdo.RESPONSE_TIMEOUT = 1.5

    # Get the PDOs from the remote
   ----->   await node.tpdo.aread()
    await node.rpdo.aread()

    # Set the remote state
    node.nmt.set_state('OPERATIONAL')

    # Set SDO
    #await node.sdo['something'].aset_raw(2)
    await node.sdo['target position'].aset_raw(2)

    i = 0
    while True:
        i += 1

        # Wait for PDO
        t = await node.tpdo[1].await_for_reception(1)
        if not t:
            continue

        # Get TPDO value
        # FIXME: Is this ok?
        #state = node.tpdo[1]['state'].get_raw()
        state = node.tpdo[1]['statusword'].get_raw()

        # If state send RPDO to remote
        if state == 5:

            await asyncio.sleep(0.2)

            # Set RPDO and transmit
            # FIXME: Using set_phys() ok?

            #node.rpdo[1]['count'].set_phys(i)
            #node.rpdo[1].transmit()

            node.rpdo[2]['target position'].set_phys(i)
            node.rpdo[2].transmit()

async def amain():

    #bus = can.Bus(interface='pcan', bitrate=1000000, recieve_own_messages=True)

    bus = can.Bus(interface='socketcan', channel='slcan0', recieve_own_messages=True)
    network = canopen.Network()
    network.bus = bus

    # Start the notifier
    loop = asyncio.get_event_loop()
    can.Notifier(bus, network.listeners, loop=loop)

    # Start two instances and run them concurrently
    #await asyncio.gather(
        #asyncio.create_task(do_loop(network, 20)),
        #asyncio.create_task(do_loop(network, 21)),

    await asyncio.gather(
        asyncio.create_task(do_loop(network, 7)),
        asyncio.create_task(do_loop(network, 10)),
    )

def main():
    asyncio.run(amain())

if __name__ == '__main__':
    main()

Example for PEAK-USB-CAN-Dongle:

on Linux-Mint-Command-Line: ip link set can0 up type can bitrate 500000

Python-Example; changed to socketcan and can0 to use PEAK-USB-CAN-Dongle:

async def amain(): bus = can.Bus(interface='socketcan', channel='can0', recieve_own_messages=True) network = canopen.Network() network.bus = bus ..... .....

sveinse commented 3 months ago

Hi. I know this is over a year past, but if you're still curious to find out what's not working, you could try to download the latest branch. I just did a refactoring of the whole SDO client logic. I removed the parallel implementation I used to have and are now using the same as official canopen, so you might be more successful if you retry now.