Not able to send CAN message to ECU using ISO_TP

A free API for the transfer of data packages according to ISO-TP (ISO 15765-2)
Post Reply
FF_PP
Posts: 4
Joined: Tue 22. Nov 2022, 17:34

Not able to send CAN message to ECU using ISO_TP

Post by FF_PP » Wed 23. Nov 2022, 10:46

Hello,

Until now, the company I'm working with was using PCAN-BASIC and managing the whole ISO-TP on their own which sometimes turns the slow comnunication due to not so efficient frame management.
As an improvement I'm trying to start with ISO-TP API.

To do so I'm trying to bring on of the examples to "our reality", example: 06_isotp_segmented_read_write
The goal was to at least be able to send the message to the bus so I can see it PCAN View, but I could not pull that off.

My current setup is a PCAN USB connected to a ECU -> This works using a PCAN BASIC so hardware should not be a problem.
ECU adresses info, Request to ECU:
-MODE: Extended
-CAN ID: 0x6F1
-ECU: 0x5E

Respondese from ECU:
-MODE: Extended
-CAN ID: 0x65E
-ECU:0xF1

What I'm trying to do is send a Tester Present message and wait for it's response, I have a trace from this:

123.495988 1 6F1 Tx d 8 5E 02 3E 00 00 00 00 00 Length = 236000 BitCount = 121 ID = 1777 // 1 OTP(1D) Atom F1->5E : SF Length: 02 [ 3E 00 ]
123.504712 1 65E Rx d 4 F1 02 7E 00 Length = 157914 BitCount = 83 ID = 1630 // 1 OTP(1E) Atom 5E->F1 : SF Length: 02 [ 7E 00 ]

To try and replicate this I have the following code:

Code: Select all

 
 // Local variables
            cantp_status res = new cantp_status();
            StringBuilder buffer = new StringBuilder(500);
            cantp_msg rx_msg = new cantp_msg();
            cantp_msg tx_msg = new cantp_msg();
            cantp_handle transmitter_handle = new cantp_handle();

            // Initialize handles 
            transmitter_handle = cantp_handle.PCANTP_HANDLE_USBBUS1;

            // Print version informations
            CanTpApi.GetValue_2016(cantp_handle.PCANTP_HANDLE_NONEBUS, cantp_parameter.PCANTP_PARAMETER_API_VERSION, buffer, 500);
            Console.WriteLine("PCAN-ISO-TP API Version : {0}", buffer);

            // Initialize channels: CAN2.0 - 500Kbit/s
            res = CanTpApi.Initialize_2016(transmitter_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize transmitter : {0}", STATUS_OK_KO(res));

            // Create and set a receive event on receiver
            System.Threading.AutoResetEvent receive_event = new System.Threading.AutoResetEvent(false);
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = Convert.ToUInt32(receive_event.SafeWaitHandle.DangerousGetHandle().ToInt32());
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = receive_event.SafeWaitHandle.DangerousGetHandle().ToInt64();
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Set receive event on receiver : {0}", STATUS_OK_KO(res));

            // Allocate tx CAN message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate tx CAN message : {0}", STATUS_OK_KO(res));

            // Allocate rx message
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_NONE);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Initialize Tx message
            uint can_id = 0x6F1;
            byte[] data = { 0x3E, 0x00 };
            res = CanTpApi.MsgDataInit_2016(out tx_msg, can_id, cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED, 2, data);
            Console.WriteLine("Initialize tx message : {0}", STATUS_OK_KO(res));

            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write DATA message : {0}", STATUS_OK_KO(res));

            // Wait a receive event on receiver
            bool wait_result = receive_event.WaitOne(100);
            Console.WriteLine("Wait a message on receiver : {0}", OK_KO(wait_result));

            // If we receive something on the receiver, read the message
            if (wait_result)
            {
                res = CanTpApi.Read_2016(transmitter_handle, out rx_msg);
                Console.WriteLine("Read message on receiver : {0}", STATUS_OK_KO(res));
                byte val = 0;
                if (CanTpApi.getData_2016(ref rx_msg, 0, out val))
                    Console.WriteLine("Check if the message is \"42\" : {0}", OK_KO(val == 0x42));
                else
                    Console.WriteLine("Check if the message is \"42\" : NOK");
            }

            // Free messages space
            res = CanTpApi.MsgDataFree_2016(ref rx_msg);
            Console.WriteLine("Free rx message : {0}", STATUS_OK_KO(res));

            // Close receive event
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = 0;
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = 0;
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Stop receive event  : {0}", STATUS_OK_KO(res));
            receive_event.Close();

            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(transmitter_handle);
            Console.WriteLine("Uninitialize transmitter : {0}", STATUS_OK_KO(res));

            // Exit
            Console.WriteLine("Press any key to exit...");
            Console.In.Read();
 
Using this I cannot see anything on PCAN View, even though PCAN STATUS is always OK, only KO when message is not received, which leads me to believe the message was transmited but some how now visble on PCAN View?

Thanks in advance for the time, and I'm looking forward for feedback.

K.Wagner
Software Development
Software Development
Posts: 896
Joined: Wed 22. Sep 2010, 13:36

Re: Not able to send CAN message to ECU using ISO_TP

Post by K.Wagner » Wed 23. Nov 2022, 13:42

Hello,
FF_PP wrote:
Wed 23. Nov 2022, 10:46
Using this I cannot see anything on PCAN View, even though PCAN STATUS is always OK, only KO when message is not received, which leads me to believe the message was transmited but some how now visble on PCAN View?
As far as I can see in the snippet code you posted, you are not registering any communication information (address mapping). Wihtout a mapping, the API doesn't know how to send or how to receive a message.
FF_PP wrote:
Wed 23. Nov 2022, 10:46
To do so I'm trying to bring on of the examples to "our reality", example: 06_isotp_segmented_read_write
If you are following the sample, then you has for sure also the part on doing an address mapping. You can see this at the line number 105 within the sample:

Code: Select all

            ...
            
            // Create a simple physical mapping: 
            //    - Source 0xF1 (transmitter), target 0x01 (receiver), CAN id 0xA1, CAN ID flow control 0xA2
            //    - Diagnostic message in a classic format
            mapping.can_id = 0xA1;
            mapping.can_id_flow_ctrl = 0xA2;
            mapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
            mapping.can_tx_dlc = 0x0;
            mapping.netaddrinfo.extension_addr = 0x00;
            mapping.netaddrinfo.format = cantp_isotp_format.PCANTP_ISOTP_FORMAT_NORMAL;
            mapping.netaddrinfo.msgtype = cantp_isotp_msgtype.PCANTP_ISOTP_MSGTYPE_DIAGNOSTIC;
            mapping.netaddrinfo.source_addr = 0xF1;
            mapping.netaddrinfo.target_addr = 0x01;
            mapping.netaddrinfo.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

            // Create the associated reversed mapping: 
            reverse_mapping = mapping;
            reverse_mapping.can_id = mapping.can_id_flow_ctrl;
            reverse_mapping.can_id_flow_ctrl = mapping.can_id;
            reverse_mapping.netaddrinfo.source_addr = mapping.netaddrinfo.target_addr;
            reverse_mapping.netaddrinfo.target_addr = mapping.netaddrinfo.source_addr;
            
            // Add mapping on channels
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref mapping);
            Console.WriteLine("Add a simple mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref reverse_mapping);
            Console.WriteLine("Add the reverse mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));            
            
            ...
Please check the PCAN-ISO-TP API documentation, chapter 4.4, for more information on address mapping.
Best regards,
Keneth

FF_PP
Posts: 4
Joined: Tue 22. Nov 2022, 17:34

Re: Not able to send CAN message to ECU using ISO_TP

Post by FF_PP » Thu 24. Nov 2022, 08:48

I've updated the code based on your sugestions but still without any sucess:

Code: Select all

	    StringBuilder buffer = new StringBuilder(500);
            UInt32 STmin;
            cantp_msg rx_msg = new cantp_msg();
            cantp_msg tx_msg = new cantp_msg();
            cantp_handle transmitter_handle = new cantp_handle();
            cantp_mapping mapping = new cantp_mapping();
            cantp_mapping reverse_mapping = new cantp_mapping();
            bool safeVersion = false; // TODO: change to true, to test the safe version of this example.

            // Initialize handles 
            transmitter_handle = cantp_handle.PCANTP_HANDLE_USBBUS1; // TODO: modify the value according to your available PCAN devices.

            // Print version informations
            CanTpApi.GetValue_2016(cantp_handle.PCANTP_HANDLE_NONEBUS, cantp_parameter.PCANTP_PARAMETER_API_VERSION, buffer, 500);
            Console.WriteLine("PCAN-ISO-TP API Version : {0}", buffer);

            // Local variables
            // Initialize channels: CAN2.0 - 500Kbit/s
            cantp_status res = CanTpApi.Initialize_2016(transmitter_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Change STmin value to 600us
            STmin = STMIN_600US;
            res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_SEPARATION_TIME, ref STmin, sizeof(UInt32));
            Console.WriteLine("Set STMIN = 600us on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Create and set a receive event on transmitter
            System.Threading.AutoResetEvent transmitter_receive_event = new System.Threading.AutoResetEvent(false);
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = Convert.ToUInt32(transmitter_receive_event.SafeWaitHandle.DangerousGetHandle().ToInt32());
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = transmitter_receive_event.SafeWaitHandle.DangerousGetHandle().ToInt64();
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Set receive event on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Allocate tx message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate tx message : {0}", STATUS_OK_KO(res));
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Create a simple physical mapping: 
            //    - Source 0xF1 (transmitter), target 0x01 (receiver), CAN id 0xA1, CAN ID flow control 0xA2
            //    - Diagnostic message in a classic format
            mapping.can_id = 0x6F1;
            mapping.can_id_flow_ctrl = 0x65E;
            mapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
            mapping.can_tx_dlc = 0x0;
            mapping.netaddrinfo.extension_addr = 0x00;
            mapping.netaddrinfo.format = cantp_isotp_format.PCANTP_ISOTP_FORMAT_EXTENDED;
            mapping.netaddrinfo.msgtype = cantp_isotp_msgtype.PCANTP_ISOTP_MSGTYPE_DIAGNOSTIC;
            mapping.netaddrinfo.source_addr = 0xF1;
            mapping.netaddrinfo.target_addr = 0x01;
            mapping.netaddrinfo.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

            // Create the associated reversed mapping: 
            reverse_mapping = mapping;
            reverse_mapping.can_id = mapping.can_id_flow_ctrl;
            reverse_mapping.can_id_flow_ctrl = mapping.can_id;
            reverse_mapping.netaddrinfo.source_addr = mapping.netaddrinfo.target_addr;
            reverse_mapping.netaddrinfo.target_addr = mapping.netaddrinfo.source_addr;

            // Add mapping on channels
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref mapping);
            Console.WriteLine("Add a simple mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref reverse_mapping);
            Console.WriteLine("Add the reverse mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Initialize Tx message containing a heavy data
            byte[] DataToSend = new byte[] {0x22, 0xF1, 0x8A };
            res = CanTpApi.MsgDataInit_2016(out tx_msg, mapping.can_id, mapping.can_msgtype, 3, DataToSend , ref mapping.netaddrinfo);
            Console.WriteLine("Initialize tx message: {0}", STATUS_OK_KO(res));

            // Write message on transmitter
            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write message on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            res = wait_and_read_msg(safeVersion, transmitter_handle, transmitter_receive_event, ref rx_msg);
            Console.WriteLine("Read loopback message on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
        
            // Free messages
            res = CanTpApi.MsgDataFree_2016(ref rx_msg);
            Console.WriteLine("Free rx message : {0}", STATUS_OK_KO(res));
            res = CanTpApi.MsgDataFree_2016(ref tx_msg);
            Console.WriteLine("Free tx message : {0}", STATUS_OK_KO(res));

            // Close receive event on transmitter
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = 0;
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = 0;
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Stop receive event on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
            transmitter_receive_event.Close();
      

            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(transmitter_handle);
            Console.WriteLine("Uninitialize transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Remove results and exit
            Console.WriteLine("Press any key to exit...");
            Console.In.Read();
I have read that chapter multiple times, and that's why I've sent you the adresses info.. I could not really understand how this works.

In my setup how can I find the right adresses? By default I've seen on another threads that, the soruce adress by default is 0xF1 (this is the PCAN USB right?) and the target should be my ECU, how do I know its adress? Is this somehow related to this info:
"
ECU adresses info, Request to ECU:
-MODE: Extended
-CAN ID: 0x6F1
-ECU: 0x5E

Respondese from ECU:
-MODE: Extended
-CAN ID: 0x65E
-ECU:0xF1
"

K.Wagner
Software Development
Software Development
Posts: 896
Joined: Wed 22. Sep 2010, 13:36

Re: Not able to send CAN message to ECU using ISO_TP

Post by K.Wagner » Thu 24. Nov 2022, 10:13

Dear,
FF_PP wrote:
Thu 24. Nov 2022, 08:48
In my setup how can I find the right adresses?
Please note that we do not know your ECU and its configuration, so you have to check yourself the mapping parameters needed for your hardware. The ECU data you posted first looks at least good to me. IT has all what you need.
FF_PP wrote:
Wed 23. Nov 2022, 10:46
-MODE: Extended
-CAN ID: 0x6F1
-ECU: 0x5E

Respondese from ECU:
-MODE: Extended
-CAN ID: 0x65E
-ECU:0xF1
FF_PP wrote:
Thu 24. Nov 2022, 08:48
I have read that chapter multiple times, and that's why I've sent you the adresses info.. I could not really understand how this works.
A mapping is not only the CAN-IDs and SA/TA addresses, but also has a type (diagnostic or remote-diagnostic), a format (normal or extended), an address type (physical or functional), and an ID type (11 or 29 bits).
This information in ISO-TP is analog to a filter in raw CAN. Only messages with a defined CAN ID provening from a defined source are received.
FF_PP wrote:
Thu 24. Nov 2022, 08:48
By default I've seen on another threads that, the soruce adress by default is 0xF1 (this is the PCAN USB right?) and the target should be my ECU, how do I know its adress?
it seems to me as you lack of ISO 15765-2 knowledge. Note that it is more difficult to understand our API if there is no background on ISO 15765-2. 0xF1 is a standardized Soucer address for a so called "Tester" (your application). As long as there is no other specification, your application should use as source 0xF1. This is not tied to a hardware directly (e.g. to a PCAN-USB or PCAN-USB Pro FD), but to your application.

I have just tested using your data by simulating the ECU with an applicaiton. You can see how the data looks like:
Mapping with 11-bits, Diagnostic, Extended
Mapping with 11-bits, Diagnostic, Extended
Mapping.PNG (75.76 KiB) Viewed 851 times
Best regards,
Keneth

FF_PP
Posts: 4
Joined: Tue 22. Nov 2022, 17:34

Re: Not able to send CAN message to ECU using ISO_TP

Post by FF_PP » Mon 28. Nov 2022, 13:49

Hello,

You are absolutly right and I'm honestly trying to lern as we go.

I was able to send the message, but the ECU does not identify it as a request message:
Image: https://ibb.co/P4rKRjc

I sent the same request using CANoe simlation instead and this is the result
Image: https://ibb.co/Wvn5Xr6

Why doesn't it identify it the same way?

This is my code:

Code: Select all

        static void Main(string[] args)
        {
            StringBuilder buffer = new StringBuilder(500);
            UInt32 STmin;
            UInt32 SA_Adress;
            cantp_msg rx_msg = new cantp_msg();
            cantp_msg tx_msg = new cantp_msg();
            cantp_handle transmitter_handle = new cantp_handle();
            cantp_mapping mapping = new cantp_mapping();
            cantp_mapping reverse_mapping = new cantp_mapping();
            bool safeVersion = false; // TODO: change to true, to test the safe version of this example.

            // Initialize handles 
            transmitter_handle = cantp_handle.PCANTP_HANDLE_USBBUS1; // TODO: modify the value according to your available PCAN devices.

            // Print version informations
            CanTpApi.GetValue_2016(cantp_handle.PCANTP_HANDLE_NONEBUS, cantp_parameter.PCANTP_PARAMETER_API_VERSION, buffer, 500);
            Console.WriteLine("PCAN-ISO-TP API Version : {0}", buffer);

            // Local variables
            // Initialize channels: CAN2.0 - 500Kbit/s
            cantp_status res = CanTpApi.Initialize_2016(transmitter_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Change STmin value to 600us
            STmin = STMIN_600US;
            res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_SEPARATION_TIME, ref STmin, sizeof(UInt32));
            Console.WriteLine("Set STMIN = 600us on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            SA_Adress = 0x10;
            res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_SEPARATION_TIME, ref SA_Adress, sizeof(UInt32));
            Console.WriteLine("Set Source Adress = 0x10 on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Create and set a receive event on transmitter
            System.Threading.AutoResetEvent transmitter_receive_event = new System.Threading.AutoResetEvent(false);
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = Convert.ToUInt32(transmitter_receive_event.SafeWaitHandle.DangerousGetHandle().ToInt32());
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = transmitter_receive_event.SafeWaitHandle.DangerousGetHandle().ToInt64();
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Set receive event on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Allocate tx message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate tx message : {0}", STATUS_OK_KO(res));
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Create a simple physical mapping: 
            //    - Source 0xF1 (transmitter), target 0x01 (receiver), CAN id 0xA1, CAN ID flow control 0xA2
            //    - Diagnostic message in a classic format
            mapping.can_id = 0x6F1;
            mapping.can_id_flow_ctrl = 0x65E;
            mapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
            mapping.can_tx_dlc = 0x08;
            mapping.netaddrinfo.extension_addr = 0x00;
            mapping.netaddrinfo.format = cantp_isotp_format.PCANTP_ISOTP_FORMAT_EXTENDED;
            mapping.netaddrinfo.msgtype = cantp_isotp_msgtype.PCANTP_ISOTP_MSGTYPE_DIAGNOSTIC;
            mapping.netaddrinfo.source_addr = 0x10;
            mapping.netaddrinfo.target_addr = 0x5E;
            mapping.netaddrinfo.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

            // Create the associated reversed mapping: 
            reverse_mapping = mapping;
            reverse_mapping.can_id = mapping.can_id_flow_ctrl;
            reverse_mapping.can_id_flow_ctrl = mapping.can_id;
            reverse_mapping.netaddrinfo.source_addr = 0xF1;
            reverse_mapping.netaddrinfo.target_addr = mapping.netaddrinfo.source_addr;

            // Add mapping on channels
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref mapping);
            Console.WriteLine("Add a simple mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref reverse_mapping);
            Console.WriteLine("Add the reverse mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Initialize Tx message containing a heavy data
            byte[] DataToSend = new byte[] {0x22, 0xF1, 0x8A };
            res = CanTpApi.MsgDataInit_2016(out tx_msg, mapping.can_id, mapping.can_msgtype, 3, DataToSend , ref mapping.netaddrinfo);
            Console.WriteLine("Initialize tx message: {0}", STATUS_OK_KO(res));

            // Write message on transmitter
            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write message on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            res = wait_and_read_msg(safeVersion, transmitter_handle, transmitter_receive_event, ref rx_msg);
            Console.WriteLine("Read loopback message on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
        
            // Free messages
            res = CanTpApi.MsgDataFree_2016(ref rx_msg);
            Console.WriteLine("Free rx message : {0}", STATUS_OK_KO(res));
            res = CanTpApi.MsgDataFree_2016(ref tx_msg);
            Console.WriteLine("Free tx message : {0}", STATUS_OK_KO(res));

            // Close receive event on transmitter
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = 0;
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = 0;
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Stop receive event on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
            transmitter_receive_event.Close();
      

            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(transmitter_handle);
            Console.WriteLine("Uninitialize transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Remove results and exit
            Console.WriteLine("Press any key to exit...");
            Console.In.Read();
        }

thanks for the time!

F.Vergnaud
Software Development
Software Development
Posts: 238
Joined: Mon 9. Sep 2013, 12:21

Re: Not able to send CAN message to ECU using ISO_TP

Post by F.Vergnaud » Mon 28. Nov 2022, 14:54

Hello,

Your code is indeed mixing CAN IDs, addresses and the type of message to send... (you can take a look at wikipedia's page "ISO 15765-2" for a short introduction).

You try to send ISO-TP messages, so you must cantp_msgtype.PCANTP_MSGTYPE_ISOTP when allocating your message.

You'll find below your code reviewed and corrected. Please take a look at the included comments where modifications were made (those comments are prefixed with WARNING:)

Code: Select all

        static void Main(string[] args)
        {
            StringBuilder buffer = new StringBuilder(500);
            UInt32 STmin;
            cantp_msg rx_msg = new cantp_msg();
            cantp_msg tx_msg = new cantp_msg();
            cantp_handle transmitter_handle = new cantp_handle();
            cantp_mapping mapping = new cantp_mapping();
            cantp_mapping reverse_mapping = new cantp_mapping();
            bool safeVersion = false; // TODO: change to true, to test the safe version of this example.

            // Initialize handles 
            transmitter_handle = cantp_handle.PCANTP_HANDLE_USBBUS1; // TODO: modify the value according to your available PCAN devices.

            // Print version informations
            CanTpApi.GetValue_2016(cantp_handle.PCANTP_HANDLE_NONEBUS, cantp_parameter.PCANTP_PARAMETER_API_VERSION, buffer, 500);
            Console.WriteLine("PCAN-ISO-TP API Version : {0}", buffer);

            // Local variables
            // Initialize channels: CAN2.0 - 500Kbit/s
            cantp_status res = CanTpApi.Initialize_2016(transmitter_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Change STmin value to 600us
            STmin = STMIN_600US;
            res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_SEPARATION_TIME, ref STmin, sizeof(UInt32));
            Console.WriteLine("Set STMIN = 600us on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // WARNING: code is irrelevant assigning SA_Adress to PCANTP_PARAMETER_SEPARATION_TIME => removed
#if false
            UInt32 SA_Adress;
            SA_Adress = 0x10;
            res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_SEPARATION_TIME, ref SA_Adress, sizeof(UInt32));
            Console.WriteLine("Set Source Adress = 0x10 on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
#endif

            // Create and set a receive event on transmitter
            System.Threading.AutoResetEvent transmitter_receive_event = new System.Threading.AutoResetEvent(false);
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = Convert.ToUInt32(transmitter_receive_event.SafeWaitHandle.DangerousGetHandle().ToInt32());
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = transmitter_receive_event.SafeWaitHandle.DangerousGetHandle().ToInt64();
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Set receive event on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Allocate tx message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_ISOTP);   // WARNING: you're trying to send ISOTP messages not CAN frames
            Console.WriteLine("Allocate tx message : {0}", STATUS_OK_KO(res));
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_ISOTP);   // WARNING: you're trying to send ISOTP messages not CAN frames
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Create a simple physical mapping: 
            //    - Source 0xF1 (transmitter), target 0x01 (receiver), CAN id 0xA1, CAN ID flow control 0xA2
            //    - Diagnostic message in a classic format
            mapping.can_id = 0x6F1;
            mapping.can_id_flow_ctrl = 0x65E;
            mapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
            mapping.can_tx_dlc = 0x08;
            mapping.netaddrinfo.extension_addr = 0x00;
            mapping.netaddrinfo.format = cantp_isotp_format.PCANTP_ISOTP_FORMAT_EXTENDED;
            mapping.netaddrinfo.msgtype = cantp_isotp_msgtype.PCANTP_ISOTP_MSGTYPE_DIAGNOSTIC;
            mapping.netaddrinfo.source_addr = 0xF1; // WARNING: based on your CAN ID, the address should be F1
            mapping.netaddrinfo.target_addr = 0x5E; // WARNING: based on your CAN ID flow control, the address should be 5E
            mapping.netaddrinfo.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

            // Create the associated reversed mapping: 
            reverse_mapping = mapping;
            reverse_mapping.can_id = mapping.can_id_flow_ctrl;
            reverse_mapping.can_id_flow_ctrl = mapping.can_id;
            reverse_mapping.netaddrinfo.source_addr = mapping.netaddrinfo.target_addr;  // WARNING: the reverse mapping MUST use the correct addresses!
            reverse_mapping.netaddrinfo.target_addr = mapping.netaddrinfo.source_addr;  // WARNING: the reverse mapping MUST use the correct addresses!

            // Add mapping on channels
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref mapping);
            Console.WriteLine("Add a simple mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
            res = CanTpApi.AddMapping_2016(transmitter_handle, ref reverse_mapping);
            Console.WriteLine("Add the reverse mapping on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Initialize Tx message containing a heavy data
            byte[] DataToSend = new byte[] { 0x22, 0xF1, 0x8A };
            res = CanTpApi.MsgDataInit_2016(out tx_msg, mapping.can_id, mapping.can_msgtype, 3, DataToSend, ref mapping.netaddrinfo);
            Console.WriteLine("Initialize tx message: {0}", STATUS_OK_KO(res));

            // Write message on transmitter
            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write message on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            res = wait_and_read_msg(safeVersion, transmitter_handle, transmitter_receive_event, ref rx_msg);
            Console.WriteLine("Read loopback message on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Free messages
            res = CanTpApi.MsgDataFree_2016(ref rx_msg);
            Console.WriteLine("Free rx message : {0}", STATUS_OK_KO(res));
            res = CanTpApi.MsgDataFree_2016(ref tx_msg);
            Console.WriteLine("Free tx message : {0}", STATUS_OK_KO(res));

            // Close receive event on transmitter
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = 0;
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = 0;
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Stop receive event on transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));
            transmitter_receive_event.Close();


            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(transmitter_handle);
            Console.WriteLine("Uninitialize transmitter {0} : {1}", cantp_handle_toShortString(transmitter_handle), STATUS_OK_KO(res));

            // Remove results and exit
            Console.WriteLine("Press any key to exit...");
            Console.In.Read();
        }
Best regards,
Fabrice

FF_PP
Posts: 4
Joined: Tue 22. Nov 2022, 17:34

Re: Not able to send CAN message to ECU using ISO_TP

Post by FF_PP » Mon 28. Nov 2022, 18:02

Hello,

Thanks for the quick response.
With your changes I managed to send the frame correctly but even though the ECU responds it seems the API ignores it, which means some maping is not correct right?

This is why I was trying to change the adress because from my understanding we should have the following maping:
Requests:
Source: 0xF1 (my APP)
Target: 0x5E (ECU)

Responses
Source: 0xF1 (ECU)
Target: 0xF1 (my APP)

Could this be the root cause for not catching the response?

F.Vergnaud
Software Development
Software Development
Posts: 238
Joined: Mon 9. Sep 2013, 12:21

Re: Not able to send CAN message to ECU using ISO_TP

Post by F.Vergnaud » Tue 29. Nov 2022, 10:22

Hello,

Be careful the sample transmits a request but only waits for the confirmation of that transmission.
Nevertheless the mappings are correctly configured: if you call the function wait_and_read_msg another time, you will read the response from the ECU (tested with a segmented response using CAN ID 0x65E).
Best regards,
Fabrice

Post Reply