[C#] TesterPresent for multiple ECUS

A free API for the communication with control devices according to UDS (ISO 14229-1)
Post Reply
rhuet
Posts: 3
Joined: Tue 28. May 2024, 14:20

[C#] TesterPresent for multiple ECUS

Post by rhuet » Tue 28. May 2024, 14:32

Hello,

Aim of my software at this moment is to detect all ECU connected & powered on the CAN bus.
For this, I would like to send TesterPresent request for each CAN ID. Here my fonction:

Code: Select all

public async Task<uds_status> SendTesterPresent(uint targetId)
    {
        while (_peakInterface.PeakHandle == cantp_handle.PCANTP_HANDLE_NONEBUS) await Task.Delay(100);

        var result = UDSApi.Reset_2013(_peakInterface.PeakHandle);
        Console.WriteLine(
            !UDSApi.StatusIsOk_2013(result)
                ? "An error occurred while trying to reset UDS: {0}"
                : "Reset UDS queues: {0}", result);

        var response = new uds_msg();
        var msg_request = new uds_msg();
        var requestConfirmation = new uds_msg();
        var configPhysical = new uds_msgconfig();
    
        configPhysical.can_id = targetId;
        configPhysical.can_msgtype =
            targetId == (uint)uds_can_id.PUDS_CAN_ID_710_REQUEST
                ? cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD
                : cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED;
        configPhysical.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_11B_NORMAL;
        configPhysical.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_FUNCTIONAL;
        configPhysical.type = uds_msgtype.PUDS_MSGTYPE_USDT;
        configPhysical.nai.source_addr = (ushort)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_OBD_FUNCTIONAL;
        configPhysical.nai.target_addr = (ushort)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
        configPhysical.nai.extension_addr = 0;
        
        result = UDSApi.SvcTesterPresent_2013(_peakInterface.PeakHandle, configPhysical, out msg_request);
        Console.WriteLine("[UDS] Execute TesterPresent service to {0} : {1}", targetId, UDSApi.StatusIsOk_2013(result));
        result = UDSApi.WaitForService_2013(_peakInterface.PeakHandle, ref msg_request, out response, out requestConfirmation);
        Console.WriteLine("[UDS] Wait for service: {0}", UDSApi.StatusIsOk_2013(result));
        UDSApi.MsgFree_2013(ref msg_request);
        UDSApi.MsgFree_2013(ref requestConfirmation);
        UDSApi.MsgFree_2013(ref response);
        // Return value
        return result;
    }
Here the Mapping:

Code: Select all

requestMapping = new uds_mapping();
            requestMapping.can_id = 0x18DA017E;
            requestMapping.can_id_flow_ctrl = 0x18DA7E01;
            requestMapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED;
            requestMapping.nai.extension_addr = 0;
            requestMapping.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_29B_EXTENDED;
            requestMapping.can_tx_dlc = 8;
            requestMapping.nai.source_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_TEST_EQUIPMENT;
            requestMapping.nai.target_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
            requestMapping.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;
            responseMapping = requestMapping;
            responseMapping.can_id = requestMapping.can_id_flow_ctrl;
            responseMapping.can_id_flow_ctrl = requestMapping.can_id;
            responseMapping.nai.source_addr = requestMapping.nai.target_addr;
            responseMapping.nai.target_addr = requestMapping.nai.source_addr;
            result = UDSApi.AddMapping_2013(receiverHandle, ref requestMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add request mapping - Success" : "Failed to add request mapping - {0}", result);
            result = UDSApi.AddMapping_2013(receiverHandle, ref responseMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add response mapping - Success" : "Failed to add response mapping - {0}", result);
            
            requestMapping = new uds_mapping();
            requestMapping.can_id = 0x18DA0A7E;
            requestMapping.can_id_flow_ctrl = 0x18DA7E0A;
            requestMapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED;
            requestMapping.nai.extension_addr = 0;
            requestMapping.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_29B_EXTENDED;
            requestMapping.can_tx_dlc = 8;
            requestMapping.nai.source_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_TEST_EQUIPMENT;
            requestMapping.nai.target_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
            requestMapping.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;
            responseMapping = requestMapping;
            responseMapping.can_id = requestMapping.can_id_flow_ctrl;
            responseMapping.can_id_flow_ctrl = requestMapping.can_id;
            responseMapping.nai.source_addr = requestMapping.nai.target_addr;
            responseMapping.nai.target_addr = requestMapping.nai.source_addr;
            result = UDSApi.AddMapping_2013(receiverHandle, ref requestMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add request mapping - Success" : "Failed to add request mapping - {0}", result);
            result = UDSApi.AddMapping_2013(receiverHandle, ref responseMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add response mapping - Success" : "Failed to add response mapping - {0}", result);
            
            requestMapping = new uds_mapping();
            requestMapping.can_id = 0x18DA147E;
            requestMapping.can_id_flow_ctrl = 0x18DA7E14;
            requestMapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED;
            requestMapping.nai.extension_addr = 0;
            requestMapping.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_29B_EXTENDED;
            requestMapping.can_tx_dlc = 8;
            requestMapping.nai.source_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_TEST_EQUIPMENT;
            requestMapping.nai.target_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
            requestMapping.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;
            responseMapping = requestMapping;
            responseMapping.can_id = requestMapping.can_id_flow_ctrl;
            responseMapping.can_id_flow_ctrl = requestMapping.can_id;
            responseMapping.nai.source_addr = requestMapping.nai.target_addr;
            responseMapping.nai.target_addr = requestMapping.nai.source_addr;
            result = UDSApi.AddMapping_2013(receiverHandle, ref requestMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add request mapping - Success" : "Failed to add request mapping - {0}", result);
            result = UDSApi.AddMapping_2013(receiverHandle, ref responseMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add response mapping - Success" : "Failed to add response mapping - {0}", result);
            
            requestMapping = new uds_mapping();
            requestMapping.can_id = 0x18DA1E7E;
            requestMapping.can_id_flow_ctrl = 0x18DA7E1E;
            requestMapping.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED;
            requestMapping.nai.extension_addr = 0;
            requestMapping.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_29B_EXTENDED;
            requestMapping.can_tx_dlc = 8;
            requestMapping.nai.source_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_TEST_EQUIPMENT;
            requestMapping.nai.target_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
            requestMapping.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;
            responseMapping = requestMapping;
            responseMapping.can_id = requestMapping.can_id_flow_ctrl;
            responseMapping.can_id_flow_ctrl = requestMapping.can_id;
            responseMapping.nai.source_addr = requestMapping.nai.target_addr;
            responseMapping.nai.target_addr = requestMapping.nai.source_addr;
            result = UDSApi.AddMapping_2013(receiverHandle, ref requestMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add request mapping - Success" : "Failed to add request mapping - {0}", result);
            result = UDSApi.AddMapping_2013(receiverHandle, ref responseMapping);
            Console.WriteLine(UDSApi.StatusIsOk_2013(result) ? "Add response mapping - Success" : "Failed to add response mapping - {0}", result);
Here how i call this function:

Code: Select all

var isNode1Exist = await _peakDetectionViewModel.SendTesterPresent((uint)uds_can_id.PUDS_CAN_ID_NODE_1_REQUEST);
Console.WriteLine("isNode1Exist: {0}", isNode1Exist == uds_status.PUDS_STATUS_OK);
Task.Delay(100).Wait();
var isNode10Exist = await _peakDetectionViewModel.SendTesterPresent((uint)uds_can_id.PUDS_CAN_ID_NODE_10_REQUEST);
Console.WriteLine("isNode10Exist: {0}", isNode10Exist == uds_status.PUDS_STATUS_OK);
Task.Delay(100).Wait();
var isNode20Exist = await _peakDetectionViewModel.SendTesterPresent((uint)uds_can_id.PUDS_CAN_ID_NODE_20_REQUEST);
Console.WriteLine("isNode20Exist: {0}", isNode20Exist == uds_status.PUDS_STATUS_OK);
Task.Delay(100).Wait();
var isNode30Exist = await _peakDetectionViewModel.SendTesterPresent((uint)uds_can_id.PUDS_CAN_ID_NODE_30_REQUEST);
Console.WriteLine("isNode30Exist: {0}", isNode30Exist == uds_status.PUDS_STATUS_OK);
Task.Delay(100).Wait();

Code: Select all

public enum uds_can_id : UInt32
    {
        PUDS_CAN_ID_NODE_1_REQUEST = 0x18DA017E,
        PUDS_CAN_ID_NODE_10_REQUEST = 0x18DA0A7E,
        PUDS_CAN_ID_NODE_20_REQUEST = 0x18DA147E,
        PUDS_CAN_ID_NODE_30_REQUEST = 0x18DA1E7E,
        
        PUDS_CAN_ID_710_REQUEST = 0x710,
The Debug Console logs:

Code: Select all

Add request mapping - Success
Add response mapping - Success
Add request mapping - Success
Add response mapping - Success
Add request mapping - Success
Add response mapping - Success
Add request mapping - Success
Add response mapping - Success
Add request mapping - Success
Add response mapping - Success
Add request mapping - Success
Add response mapping - Success
Reset UDS queues: PUDS_STATUS_OK
[UDS] Execute TesterPresent service to 416940414 : True
[UDS] Wait for service: False
isNode1Exist: False
Reset UDS queues: PUDS_STATUS_OK
[UDS] Execute TesterPresent service to 416942718 : True
[UDS] Wait for service: False
isNode10Exist: False
Reset UDS queues: PUDS_STATUS_OK
[UDS] Execute TesterPresent service to 416945278 : True
[UDS] Wait for service: False
isNode20Exist: False
Reset UDS queues: PUDS_STATUS_OK
[UDS] Execute TesterPresent service to 416947838 : True
[UDS] Wait for service: False
isNode30Exist: False
My issue is only the frame PUDS_CAN_ID_NODE_1_REQUEST = 0x18DA017E is send
Capture d'écran 2024-05-28 142916.png
Capture d'écran 2024-05-28 142916.png (10.16 KiB) Viewed 2587 times

Thanks in advance,

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

Re: [C#] TesterPresent for multiple ECUS

Post by F.Vergnaud » Wed 29. May 2024, 10:11

Hello,

Are you sure of the ISOTP addressing format you use? Your mappings are using PUDS_MSGPROTOCOL_ISO_15765_2_29B_EXTENDED...
"ISOTP Extended" addressing is not to be confused with "Extended CAN IDs": ISOTP extended addressing roughly means that the "ISOTP target address" will be sent in the first byte of the CAN Data.

Based on the format of your CAN IDs and the fact that all your mappings use the same source/target couple, I'd say that you don't really know the ISOTP networking information you are trying to map.
- your application must have an unique address,
- all ECUs must have a unique address,
- a mapping links a CAN ID with a one way communication between 2 ISOTP addresses.

The CAN IDs of your mappings use the same pattern as the ISOTP Fixed Normal addressing format: 0x18DAXXYY where XX is Target Address and YY Source address.
If your ECU communicates with the ISOTP addressing format "FIXED NORMAL", then you don't need to configure mappings, this is handled automatically by the API.
In SendTesterPresent, a check exists for a possible CAN ID of 710, a 11 bit CAN ID requires a mapping: check the specification of your ECU to know if it uses ISOTP extending format addressing or ISOTP Normal addressing.
Please check the PCAN-UDS manual "§4.3 UDS and ISO-TP Network Addressing Information" for more information on mappings.

Finally, your function SendTesterPresent uses Functional target type... this is used to send a request without specifying a target address. You will receive responses from all listening ECUs, but for this you must use the corresponding function WaitForServiceFunctional_2013.
Best regards,
Fabrice

rhuet
Posts: 3
Joined: Tue 28. May 2024, 14:20

Re: [C#] TesterPresent for multiple ECUS

Post by rhuet » Wed 29. May 2024, 11:28

Thanks you for your answer,

I have removed all mapping.

Things I don't understand is this working well:
Capture d'écran 2024-05-28 142916.png
Capture d'écran 2024-05-28 142916.png (185.95 KiB) Viewed 2566 times
Capture d'écran 2024-05-29 112406.png
Capture d'écran 2024-05-29 112406.png (4.18 KiB) Viewed 2566 times

But this sent always first target id:
Capture d'écran 2024-05-29 112809.png
Capture d'écran 2024-05-29 112809.png (108.45 KiB) Viewed 2566 times
Capture d'écran 2024-05-29 112551.png
Capture d'écran 2024-05-29 112551.png (180.01 KiB) Viewed 2566 times
Capture d'écran 2024-05-29 112715.png
Capture d'écran 2024-05-29 112715.png (8.33 KiB) Viewed 2566 times
Best regards

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

Re: [C#] TesterPresent for multiple ECUS

Post by F.Vergnaud » Wed 29. May 2024, 11:52

Hello,

First problem is you specify a parameter targetId that you never use in the function SendTesterPresent unless in your log message, please double check your code.
Second initialize the uds_msgconfig according to what I said previously:
- use PUDS_MSGPROTOCOL_ISO_15765_2_29B_FIXED_NORMAL.
- initialize source_addr and target_addr according to the context of the CAN ID
- do not set the can_id field, use 0xFFFFFFFF (-1) otherwise you inform the API that it can be used to override the network address information if no mapping is found. The API will configure msgRequest to send a UUDT message but will not be able to receiving a matching response as your network address information is wrong.

Explaining protocol ISO-15765-2 is outside the scope of our support, please check first the documentation and the ISO-TP/UDS samples to better understand how ISOTP and UDS communications work.
Best regards,
Fabrice

rhuet
Posts: 3
Joined: Tue 28. May 2024, 14:20

Re: [C#] TesterPresent for multiple ECUS

Post by rhuet » Wed 29. May 2024, 12:02

Thanks you very much,

I understand better now.

Best regards

Post Reply