lishen2 / isotp-c

An implementation of the ISO-TP (ISO15765-2) CAN protocol in C
MIT License
189 stars 70 forks source link

multiple frame transmition with different ID's #8

Closed dnrelectronica closed 2 years ago

dnrelectronica commented 4 years ago

Hi all,

I am trying to understand how the library can separate messages with different ID's. For example.. if i have 3 devices connected on the can bus and device A tries to send a multiple frame message on the bus with iso tp, and half way of the message sending device B starts also with a multiple frame message sending on the same bus. How can the receiving devices C determine from who is the frame ? Do i really need to make a g_link handle for every possible Arbitration ID i have??? this is a lot, since in OBDII systems for example this is a large list of message id's.

I hope you understand my question .

Kind Regards,

Corné

dnrelectronica commented 4 years ago

anyone??

j3kestrel commented 4 years ago

Yes, different IsoTpLink instance for each connection. That is where the state of the communication link is stored and the state is different for each.

dnrelectronica commented 4 years ago

For each ‘connection’ ?? You mean for every message id crossed the CAN network I guess? Assume a car has a protocol with 300 different msg id’s . This means 300 IsoTpLink instanced with each having their own buffers?? This is insane, and should be much more efficient imho. Please let me know what you think about a solution for this. Kind regards, corne

j3kestrel commented 4 years ago

Most can/message id's will not carry the iso-tp protocol. I would expect no more than 1 IsoTpLink instance per node on the CAN bus. ...and even then only if you needed to talk to all of them at once which isn't likely for the services that would be using iso-tp. Most of the run-time data won't be iso-tp. In any case, there really is no way around it. You must track the state of transfer for each node/endpoint/connection.

If you are connecting to 300 nodes simultaneously, that would be most of 3MB of RAM to maintain the state and have buffers for each of the nodes. I would expect that a PC class computer would be used, not an embedded microcontroller. For a PC class computer, 3MB is nothing. The RAM on such systems is generally measured in Gigabytes these days.

If one did need to handle 300 nodes, didn't have that much RAM to work with and only need to communicate with a small number of nodes at any one time, one could allocate a small pool of IsoTpLink instances and associated rx/tx buffers. If the state of messaging is tracked, each time a new transfer is initiated to or from a node you could allocate from the pool, initialize, do the transfer and then return the data structures to the pool to be reused. That would be a very specialized case, but I'm pretty sure I could make this library handle it without too much grief.

dnrelectronica commented 4 years ago

hi @j3kestrel ,

I don't think you understand my problem. The only reason why i am looking for ISO-TP is because i would like to send packaged over the CAN network which are larger than 8 bytes. Only for this simple reason i use ISO-TP, and to be honest, i don't like it very much because it is overhead on top of the CAN Bus. I prefer to use only 8 byte messages only, but sometimes nodes need to send a text string for example which is lets say 34 bytes. Is there an other way to send such a message over the network without ISO-TP?

There is also a misunderstanding in the number of nodes you mention. I didn't mean 300 nodes, but 300 different message id's. this is the ID in the CAN frame, can be 11 or 29 bit. So to be more clear, in my system there will be only 10 CAN nodes in the network i guess. These 10 nodes are all sending and receiving data. The problem to solve is: How can these 10 nodes communicate and send/receive larger packets than 8 bytes simultaneously?

Automotive- example:

define CAN_ID_ENGINE_MOTOR_RPM 0x100 (16-bit value, fits in one can frame)

define CAN_ID_ENGINE_MOTOR_START 0x101 (boolean value, fits in one can frame)

define CAN_ID_ENGINE_MOTOR_STATUS 0x102 (32 char string, fits NOT in one can frame)

So, what you saying is: the automotive industry will try to fit every message in a 8 byte message? And if it doesn't fit, it will break it up into parts and send them as Part1/4, part 2/4 , part3/4 part 4/4? The receiving side should create a separate buffer for this message as it needs to store the parts, and can process the whole message is all parts are received. But this is only for ONE message id. what if in the same time another node sends also a multi-part message over the network. the receiver should create a buffer for this message also to keep track of the parts it is receiving.

I hope you understand now more my problem. Please could you help to explain how you would solve this issue??

kind regards,

Corne

j3kestrel commented 4 years ago

In automotive, CAN_ID_ENGINE_MOTOR_STATUS would not be sent as a string. It would be sent as a set of flags, enum's and values, depending on what sort of state information is being communicated. No iso-tp involved. All the data is divided up into as many 8 byte message types as needed and a can-id is assigned to each message type.

Iso-tp is used for higher level protocols, like UDS, that need to transmit larger blocks of data. It would be very unusual to need more than one such connection per node. Each block is formatted with some sort of a header that permits identifying what type of data is in it. The node would be required to complete the sending of one iso-tp packet before starting the next.

Look at your data. Does it need to be strings and large buffers? Or is it a set of smaller state values that fit in bits, bytes and ints? If the former, use a single iso-tp connection and define the messages to include a header to identify what is in the message. You could even use JSON strings. If it is the latter, then break you data up into 8 byte CAN frames, and assign a unique can-id to each. Don't use iso-tp in this case.

In very simple cases, there is a 3rd option. I sometimes just stream bytes over a single can-id. This is generally for a debug console output. ...gives me a place to send printf() output. The receiver just keeps adding the received bytes to a buffer or (more often) prints them to the screen.

I suppose using this last strategy, you could treat can as a serial stream of bytes just like a conventional UART/RS-232 connection. ...in fact I have done this before. Here you use some sort of escape sequence or marker to indicate the beginning and/or end of a block of data. If all the data is ASCII, a newline could be that marker. However, this will not be robust to lost/dropped CAN frames.

lishen2 commented 2 years ago

@j3kestrel Good Job.