pylessard/python-can-isotp

Not able to transmit data for classic CAN FD (single frame size= 64 bytes)

FarhatJ opened this issue ยท 24 comments

My requirement is to transmit data from can to tcp (for classic CANTp speed control service)
I am trying to transmit single frame size of 64 bytes on CAN channel using isotp.stack().
Similar to what we have here

My Code snippet:

import can
class VirtualBus:
    def __init__(self, net_channel: str = '0'):
        self.bus = can.Bus(channel=net_channel,
                           interface='vector',
                           receive_own_messages=True,
                           app_name='CANoe',
                           bitrate=500000)
bus = VirtualBus(net_channel=channel)
print(bus.bus.channel_info)
address = isotp.Address(addressing_mode=isotp.AddressingMode.Normal_29bits, rxid=rxid, txid=txid)

stack = isotp.CanStack(bus=bus.bus,
                                    address=address,
                                    error_handler=print,
                                    params={'tx_padding': 0xCC,
                                    'can_fd': True,
                                    'tx_data_length': 64,
                                     'rx_consecutive_frame_timeout': 100000})
stack.send(data)

while stack.transmitting():
    stack.process()
    time.sleep(stack.sleep_time())

Getting error as:
"C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\broadcastmanager.py", line 281, in _run self.bus.send(self.messages[msg_index]) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 536, in send self._send_sequence([msg]) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 543, in _send_sequence return self._send_can_msg_sequence(msgs) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 556, in _send_can_msg_sequence xl_event_array = (xlclass.XLevent * message_count.value)( File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 580, in _build_xl_event xl_event.tagData.msg.data = tuple(msg.data) RuntimeError: (c_ubyte_Array_8) <class 'IndexError'>: invalid index (c_ubyte_Array_8) <class 'IndexError'>: invalid index

Note : when I tried to change the value of 'tx_data_length' more than 8 bytes, its throwing the above error.
Also to add CAPL script with the same rxid and txid works perfect.
Is something in the canoe application that i have to enable for CAN FD??

Am I missing anything?? Any parameter that I need to set? Please help me out here.

Your code seems right.
The stack trace talks about Vector, but you are using a virtual bus. That is strange. Looks like python-can is doing something weird. Can you share your lib version?

@pylessard Yes I am using Virtualbus, app_name=CANoe and using python-can==4.0.0.
I hope you talking about Python-can module version when you said lib version.
I am new to this I may not understand some terminology sorry if I am wrong.

Ok,
I have never used the VirtualBus. My initial assumption was that it was not tied to any hardware. Now seeing your stack trace pointing to Vector code and you mention that your appname is CANoe (vector software), I think I might not understand what a virtual bus does.

In any case, I think your issue is on the python-can layer. Try sending raw frames without the isotp layer and see where you can get. I made all my tests using a VectorBus or a SocketCanBus.

Regards

@pylessard I have tried with CAPL script with the same rxid and txid and it works for 64 bytes of frame size.
Can you please point it to me how to send raw frames without isotp through python script?? an example would be helpful.

see python-can doc: https://python-can.readthedocs.io/en/stable/interfaces/virtual.html

Are you transmitting over a hardware bus? Why not use a VectorBus if you use vector hardware?

@pylessard will this be helpful in routing from CAN to TCP (for classic CANTp Speed control Service).
I guess the link you sent is for udp and can mirroring packages.
I do not have much experience in these, but tryign to explore.

Why don't you explain what you are trying to do? The more it goes, the more I am confused :)

I just noticed that you wrote the VirtualBus class!
On what hardware are you trying to transmit. that's the important part

So sorry to confuse you. I am trying to transmit on Vector Canoe application.

I am using CANTp Speed control Service for classic component (Canoe as a gateway)
CANTp implementation is as mentioned here https://www.linkedin.com/pulse/can-tp-iso-15765-2-vivek-maurya%3FtrackingId=iqLQKTqMSmGceHGb9u0R6A%253D%253D/?trackingId=iqLQKTqMSmGceHGb9u0R6A%3D%3D

Now I am writing a testcase to transmit data on CAN channel-> and CANTp will route data on tcp -> Ethernet (tcp).
I am successfully able to route data from can to tcp for 8 bytes of frame size using isotp.stack as shown above ('tx_data_length': 8).
Now I am testing same concept but for 64 bytes of frame and thats where i get this error.

I even tried what you have suggested me above: #85 (comment)

with concurrent.futures.ThreadPoolExecutor() as executor:
            future = executor.submit(self.listen_for_port, port=port)

            msg0 = can.Message(arbitration_id=0x580, dlc=15, is_fd=True,
                               is_extended_id=True, bitrate_switch=True,
                               data=[3, 3, 3, 3, 3, 3, 3, 3, 3, 3])

            msg1 = can.Message(arbitration_id=0x582, dlc=15, is_fd=True,
                               is_extended_id=True, bitrate_switch=True,
                               data=[3, 3, 3, 3, 3, 3, 3, 3, 3, 3])

            messages = [msg0, msg1]
            vbus1.send_messages(messages, 1000)
            time.sleep(2)
            udp_frames = future.result()

I am getting the same error when data is more than 8.
verror

When data is 8 or less than 8, transmission works
can message-canoe

Ok.
I do not know what CANTp Speed control Service is unfortunately. I am not sure if you mean the IsoTP protocol.
I assume that your CAN trasnceiver is a vector transceiver. Can you confirm that? Please give the model number.

The screenshot above clearly shows that the issues relies at python-can level.
Can you try updating python-can? Also update your Vector driver. Are you sure the hardware you are using supports CAN-FD?

Okay I dont think so I am using Hardware (not connected with physical device), I am using Vector CANoe application Version 16.0 on Windows https://www.vector.com/int/en/support-downloads/download-center.
And yes, the application supports CAN FD because the same thing works with Capl script but not with isotp protocol.

And yes let me upgade Python-can to 4.2.0 and test.

Hmm, ok so it's a purely software link that passes through vector library.
I never used that, sorry. I suggest you raise an issue on python-can repo and see what you can get.

I'm looking at their documentation and see that they have a hardware type called : XL_HWTYPE_VIRTUAL
https://python-can.readthedocs.io/en/stable/interfaces/vector.html#
Also, I know that python-can calls functionality from the Vector dll, which the manual is here. Maybe you can figure what's wrong : https://cdn.vector.com/cms/content/products/XL_Driver_Library/Docs/XL_Driver_Library_Manual_EN.pdf

Sorry for not being more useful than that, but this repo deals with the isotp layer and my knowledge is limited regarding the underlying layers.

@pylessard thank you so much for your input, i will definitly read what you have mentioned, and will raise the issue in Python-can repo.

Thank you so very much.

Updated python-can to 4.2.0 still the same error.
Raised issue under python-can repo hardbyte/python-can#1582

Good, I will monitor it.
You should show how you create your bus object :)

@FarhatJ : I've reviewed python-can code. I'll continue here not to interfere with the other thread.
I think you are not posting the error that matches the code you are showing.

  • First, the stack trace that you show is for python-can 4.0 while you say you have python-can 4.2.
  • The bus constructor in this thread does not set fd=True, which match the stack trace. In the other thread it does. I think you are not getting the same stack trace when you set fd=True.

Am I guessing right? If so, please rectify, otherwise help will be impossible

@pylessard as you suggested to upgrade python-can 4.2.0, even with v4.2 I got the same error and then i started the other thread.
After raising my issue in python-can repo, zariiii9003 suggested me to initialize fd=True while creating bus obj (previously this was missing).
So now my setup is:

  1. Using python-can 4.2.0
  2. With fd=True in the other thread is not giving me error anymore but still can not see full data in single frame as i have shown the canoe trace but dlc does vary depepnding on the length of data I am sending.

Now about this thread, the issue that i reported is the same where I am using isotp protocol to transmit data on CAN channel.
I have updated bus obj with fd=True in this code as well but now I am getting some other error.

E can.exceptions.CanInitializationError: The requested settings could not be set for channel 0. Another application might have set incompatible settings. These are the currently active settings: bitrate: 533333, data_bitrate: 533333, sjw_abr: 1, tseg1_abr: 18, tseg2_abr: 6, sam_abr: 1, sjw_dbr: 1, tseg1_dbr: 18, tseg2_dbr: 6, output_mode: 1, can_op_mode: CAN FD.

canoe-fd-error

Not sure if this has something to do with Vector CANoe channel\network configuration. I am on it, I am read Vector CANoe network config for CAN FD.

I am basically trying to find the misisng parameter in my code, if in the other thread i can get CAN FD working using can.Message(), I can try the same solution for this (i.e transmiting using isotp protocol).
I am so sorry for this confusion, I myself trying my best to debug and find where the issue is. (I am sure its in my code but do not know what I am missing)

This is error is totally different now. The first issue is solved, python-can now doing the right thing.
Your new issue is that Vector does not allow you to use this set of settings because CANoe have different settings. (exactly what the error says).

The way Vector works is that only one process can "own" the device, thus able to configure it. In your case, it is probably CANoe. the Vector lib (which python-can uses) is not letting you change a parameter that CANoe has set, bitrate maybe? Above it is 500k but in your error it is 533333. bitrate is an optional parameter to the VectorBus, maybe leave it to default None?

This is a good point, thanks.

I just tried to keep bitrate default (did not set bitrate parameter). still getting the error as:

E can.exceptions.CanInitializationError: The requested settings could not be set for channel 0. Another application might have set incompatible settings. These are the currently active settings: bitrate: 533333, data_bitrate: 533333, sjw_abr: 1, tseg1_abr: 18, tseg2_abr: 6, sam_abr: 1, sjw_dbr: 1, tseg1_dbr: 18, tseg2_dbr: 6, output_mode: 1, can_op_mode: CAN FD.

You must adapt your bit timings either in CANoe or in python-can:

timing = can.BitTimingFd.from_bitrate_and_segments(
    f_clock=80_000_000,
    nom_bitrate=533_333,
    nom_tseg1=18,
    nom_tseg2=6,
    nom_sjw=1,
    data_bitrate=533_333,
    data_tseg1=18,
    data_tseg2=6,
    data_sjw=1,
)
with can.Bus(interface="vector", channel=0, timing=timing) as bus:
    print(bus)

The bitrates and the sample points must match, otherwise an exception is thrown.

@pylessard omg, thank you so very much, with the bit timing you mentioned above I am successfully able to see single frame of 64 bytes of data.
Now I will figure it out how to adapt this for CAN 2.0 and CAN FD all together.
You were really helpfull.

Just to summerize the issue and solution:

  1. Their were no issue in the isotp protocol.
  2. I was missing parameter fd=True in the can bus initialization.
  3. Also added can.BitTimingFd.from_bitrate_and_segments() as it is mentioned above.
  4. Also enabled CAN FD in the Canoe application Network Hardware configuration.

network-config

Credits goes to @zariiii9003 :)
I'm closing this issue

Just to update this is how my final code looks like for 64 bytes of single frame( Dont forget to update Network Hardware config in the CANoe application as mentioned in above image)

Can bus obj creation -> added bit timings, removed bitrate and set fd=True.

import can
class VirtualBus:
    def __init__(self, net_channel: str = '0'):

        timing = can.BitTimingFd.from_bitrate_and_segments(
        f_clock=80_000_000,
        nom_bitrate=533_333,
        nom_tseg1=18,
        nom_tseg2=6,
        nom_sjw=1,
        data_bitrate=533_333,
        data_tseg1=18,
        data_tseg2=6,
        data_sjw=1,
      )
      self.bus = can.Bus(channel=net_channel,
                                     interface='vector',
                                     receive_own_messages=True,
                                     app_name='CANoe',
                                     timing=timing,
                                     fd=True)

python script to transmit data: list on mentioned CAN channel.

bus = VirtualBus(net_channel=channel)
print(bus.bus.channel_info)
address = isotp.Address(addressing_mode=isotp.AddressingMode.Normal_29bits, rxid=rxid, txid=txid)

stack = isotp.CanStack(bus=bus.bus,
                                    address=address,
                                    error_handler=print,
                                    params={'tx_padding': 0xCC,
                                    'can_fd': True,
                                    'tx_data_length': 64,
                                    'tx_data_min_length': 64,
                                     'rx_consecutive_frame_timeout': 100000})
stack.send(data)

while stack.transmitting():
    stack.process()
    time.sleep(stack.sleep_time())