canopen
canopen copied to clipboard
Error when using: network.scanner.search()
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
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
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)
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
Hello Svein, hello Samuel, Thank you for your quick responce. I tried to check your improvements, but without success:
- 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: - 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
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.
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?
You should be able to close issues you opened yourself. You write a comment and press the "Close with comment" Button.