hardbyte / python-can

The can package provides controller area network support for Python developers
https://python-can.readthedocs.io
GNU Lesser General Public License v3.0
1.31k stars 604 forks source link

slcan interface needs some time-tweaking (Possible solution provided) #1746

Open K1BSS opened 9 months ago

K1BSS commented 9 months ago

Describe the bug

Messages are truncated while using send command. Messages are truncated while using close command.

To Reproduce

Code as example. Requires python-can and pyserial modules. Windows PC and CANable with original firmware: https://github.com/normaldotcom/canable-fw Counter-interface: PCAN USB dongle and oscilloscoop

Problem 1: When looping messages within the "with can.Bus", one can see on the scope that the messages are corrupted/truncated. Problem 2: When looping messages main, one can see that the last message in the "with can.Bus" is truncated.

Possible solution: End the _write-function with: "time.sleep(3.0e-5)" Begin the close-function with: "time.sleep(3.0e-5)"

Additional information, experimentally obtained: 10kbps: total fail (!) 20kpbs: requires 5.0e-3 seconds 50kpbs: requires 2.0e-3 seconds 83kpbs: requires 2.0e-3 seconds 100kpbs: requires 6.0e-4 seconds 125kpbs: requires 6.0e-4 seconds 250kpbs: requires 5.0e-5 seconds 500kpbs: requires 3.0e-5 seconds 750kpbs: other side (PCAN in this case) has no setting for 750, it has 800 which is not compatible 1000kpbs: requires 4.0e-6 seconds or even lower

Expected behavior

Truncated messages: seen on a oscilloscoop. PCAN viewer tels me stuffing errors. The error will result in resending infinite retrying messages.

Additional context

OS and version: Windows 11 Python version: Python 3.12 python-can version: 4.3.1 pyserial version: 3.5 python-can interface/s (if applicable): slcan Hardware interface: CANable 2.0 Pro IDE: PyCharm recent version Oscilloscope: Rigol DS1000-series Counter-interface: PCAN USB isolated version and PCAN-View software

Possible solution: End the _write-function with: "time.sleep(3.0e-5)" Begin the close-function with: "time.sleep(3.0e-5)"

Traceback and logs None See code example. ``` def send_one(): with can.Bus(interface="slcan", channel="COM7@115200", bitrate=500000, sleep_after_open=0.0) as bus: msg = can.Message( arbitration_id=0x555, data=[0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55], is_extended_id=False ) try: j = 0 while j < 2: bus.send(msg) j = j + 1 except can.CanError: print("Message NOT sent") if __name__ == "__main__": i = 0 while i < 2: send_one() i = i + 1 ```