Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when using: network.scanner.search() #369

Open
GIT1RWM2AR opened this issue Apr 8, 2023 · 5 comments
Open

Error when using: network.scanner.search() #369

GIT1RWM2AR opened this issue Apr 8, 2023 · 5 comments

Comments

@GIT1RWM2AR
Copy link

Hello to all,
I find an error, fixed it with a workaround,
but maybe the CAN, CANopen specialists know
the correct solution.

network.scanner.reset()
network.scanner.search() ---> Error
slcan0 75B [1] 7F
slcan0 60A [8] 40 00 10 00 00 00 00 00
slcan0 58A [8] 43 00 10 00 00 00 00 00
slcan0 601 [8] 40 00 10 00 00 00 00 00
slcan0 602 [8] 40 00 10 00 00 00 00 00
slcan0 603 [8] 40 00 10 00 00 00 00 00
slcan0 604 [8] 40 00 10 00 00 00 00 00
slcan0 605 [8] 40 00 10 00 00 00 00 00
slcan0 606 [8] 40 00 10 00 00 00 00 00
slcan0 607 [8] 40 00 10 00 00 00 00 00
slcan0 608 [8] 40 00 10 00 00 00 00 00
slcan0 609 [8] 40 00 10 00 00 00 00 00
slcan0 60A [8] 40 00 10 00 00 00 00 00
slcan0 60B [8] 40 00 10 00 00 00 00 00
slcan0 60C [8] 40 00 10 00 00 00 00 00
slcan0 60D [8] 40 00 10 00 00 00 00 00
slcan0 587 [8] 43 00 10 00 00 00 00 00
slcan0 588 [8] 43 00 10 00 00 00 00 00
slcan0 58A [8] 43 00 10 00 00 00 00 00
slcan0 707 [1] 7F
File "/home/ar/Schreibtisch/WING-Test-1/Wing-Main-1.py", line 75, in
network.scanner.search()
File "/home/ar/.local/lib/python3.10/site-packages/canopen/network.py", line 404, in search
self.network.send_message(0x600 + node_id, sdo_req)
File "/home/ar/.local/lib/python3.10/site-packages/canopen/network.py", line 216, in send_message
self.bus.send(msg)
File "/home/ar/.local/lib/python3.10/site-packages/can/interfaces/socketcan/socketcan.py", line 774, in send
sent = self._send_once(data, channel)
File "/home/ar/.local/lib/python3.10/site-packages/can/interfaces/socketcan/socketcan.py", line 791, in _send_once
raise can.CanOperationError(
can.exceptions.CanOperationError: Failed to transmit: No buffer space available [Error Code 105]

Workaround: time.sleep(0.001)

def search(self, limit: int = 127) -> None:
    """Search for nodes by sending SDO requests to all node IDs."""
    if self.network is None:
        raise RuntimeError("A Network is required to do active scanning")
    sdo_req = b"\x40\x00\x10\x00\x00\x00\x00\x00"
    for node_id in range(1, limit + 1):
        self.network.send_message(0x600 + node_id, sdo_req)
        time.sleep(0.001)

Is there a better solution?

Thank you in advance;
You did a great job!

Best regards
Armin

@christiansandberg: Can I send you a direct E-Mail for some other questions?
Thanks

@sveinse
Copy link
Contributor

sveinse commented Apr 8, 2023

The code in search is sending an SDO request to all nodes, which creates a lot of packages. My guess to the root cause is that python-can or the CAN driver is accepting data from canopen faster than it's able to process and fills up. I'm uncertain if this is a canopen issue, unfortunately.

According to the python-can API the self.bus.send() function innetwork.py, Network.send_message() accepts a timeout argument. The docs sais:

    :param timeout:
       If > 0, wait up to this many seconds for message to be ACK'ed or
       for transmit queue to be ready depending on driver implementation.
       If timeout is exceeded, an exception will be raised.
       Might not be supported by all interfaces.
       None blocks indefinitely.

Please try changing this code in Network.send_message(). https://github.com/christiansandberg/canopen/blob/master/canopen/network.py#L213-L214. Does this work at all?

        with self.send_lock:
            self.bus.send(msg, timeout=0.01)

@samsamfire
Copy link
Contributor

samsamfire commented Apr 9, 2023

GIT1RWM2AR, change your transmit buffer length in socketcan to something like 1000.
If you are using can0 this could be something like:
sudo ip link set can0 type can txqueuelen 1000

@GIT1RWM2AR
Copy link
Author

Hello Svein,
hello Samuel,
Thank you for your quick responce.
I tried to check your improvements, but without success:

  1. Sveins solution, didn't changed the result:
    --> can.exceptions.CanOperationError: Failed to transmit: No buffer space available [Error Code 105]
    Even: self.bus.send(msg, timeout=1.01)
    --> No improvements:
  2. Samuels suggestion seems to point to the solution with an increase of
    the txquelen, but
    I ended up in the problems of CAN / Linux implementations;
    and in both I am no expert:
    --> I try to show my investigations:

For Info: Here I show the startup-commands for Thomas Fischl: USBtin and Linux-CAN-HW-Interface:
#!/bin/bash
echo "Start slcan0 interface for /dev/ttyACM0"
cd can-utils/
sudo modprobe can
sudo modprobe can-raw
sudo modprobe slcan
echo "Set CAN-Interface to 500kBaud"
sudo ./slcan_attach -f -s6 -o /dev/ttyACM0
sudo ./slcand ttyACM0 slcan0
sudo ifconfig slcan0 up
candump slcan0

Here is the suggested improvement:
--> sudo ip link set slcan0 type can txqueuelen 1000
This is the error-message:
==> can: unknown option "txqueuelen"
Because of: https://www.suse.com/support/kb/doc/?id=000019932
2. Take note that the name for the txqueuelen setting used by the "ifconfig", "ip" and "systool" commands are "txqueuelen", "qlen" and "tx_queue_len"

I tried: txqueuelen, qlen, tx_queue_len ---> all with the same negative result

To get more information:
ip -details -statistic link show slcan0
6: slcan0: <NOARP,UP,LOWER_UP> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
link/can promiscuity 0 minmtu 0 maxmtu 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
RX: bytes packets errors dropped missed mcast
28919 28674 0 0 0 0
TX: bytes packets errors dropped carrier collsns
2408 301 0 0 0 0

---> group default qlen 10

---> Under Linux I found:
---> https://elixir.bootlin.com/linux/v4.14/source/drivers/net/can/slcan.c#L443

    dev->[tx_queue_len](https://elixir.bootlin.com/linux/v4.14/C/ident/tx_queue_len)	= 10;

For me, this looks like a hard coded value

--> At this point I ended up, because I am not familiar with Linux driver handling and debugging.

Any further ideas, how to get an easy way of improvement?

Maybe in some future time, I am experienced to do it,
additionally to handle lost hardware bus connections
(USB/CAN) to do a plug and play reconnect.
Until then, I will work with my not so perfect delay time of one millisecond.

Many thanks and
Best regards

Armin

@samsamfire
Copy link
Contributor

I'm not really familiar with SLCAN and I don't know if the underlying hardware is very capable.
Anyway, my bad the command is without the "type can" as so:
sudo ip link set slcan0 txqueuelen 1000
Increasing the txqueuelen is not magic though, if your hardware is not capable of sending at the pace your emitting then you will end up with the same error. This option is only really useful when your sending frames in bursts (like with the scan function) and your driver hasn't got the time to process all tx frames.

@GIT1RWM2AR
Copy link
Author

Hello Samuel,
now with your help,

sudo ip link set slcan0 txqueuelen 1000

it is working perfectly.

I tested it down till 115.
In future I will use 130 because I know:
for node_id in range(1, limit + 1):
and limit = 127
(CANopen-Bus can have maximum 128 nodes)

sudo ip link set slcan0 txqueuelen 130

Thank you very much!
Armin

PS.
Sorry for the bold text, in my last comment: This comment-function did it automatically.
How do I set this issue to solved?
Is this Christians task?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants