Trouble communicating with car's ECU using Tactrix OpenPort and J2534 AP

179 Views Asked by At

I'm trying to request the RPM from my car's instrument cluster using the Tactrix OpenPort and J2534 API. The request seems to be sent, the device's light blinks but I am not receiving any of the data into the console.

To point it out drivers and as well API and some samples can be found on this link. After you install everything you can navigate to program files OpenECU and there you would find the samples folder.

This is the first version of the program:

#include <iostream>
#include <tchar.h>
#include <windows.h>
#include <conio.h>
#include <time.h>

#include "J2534.h"

J2534 j2534;

void reportJ2534Error()
{
    char err[512];
    j2534.PassThruGetLastError(err);
    printf("J2534 error [%s].\n", err);
}

int _tmain(int argc, _TCHAR* argv[])
{
    unsigned long devID;
    unsigned long chanID;

    // Initialization
    if (!j2534.init())
    {
        printf("Can't connect to J2534 DLL.\n");
        return 0;
    }

    if (j2534.PassThruOpen(NULL, &devID))
    {
        reportJ2534Error();
        return 0;
    }

    if (j2534.PassThruConnect(devID, CAN, 0, 500000, &chanID))  // 500000 is the baud rate
    {
        reportJ2534Error();
        return 0;
    }

    // Send RPM request
    PASSTHRU_MSG txmsg;
    txmsg.ProtocolID = CAN;
    txmsg.RxStatus = 0;
    txmsg.TxFlags = 0;
    txmsg.DataSize = 8;
    txmsg.Data[0] = 0x02;  
    txmsg.Data[1] = 0x71;  // CAN ID 714 high byte
    txmsg.Data[2] = 0x4;   // CAN ID 714 low byte
    txmsg.Data[3] = 0x22;
    txmsg.Data[4] = 0x22;  
    txmsg.Data[5] = 0xD1;  
    txmsg.Data[6] = 0x55;
    txmsg.Data[7] = 0x55;

    unsigned long numTxMsg = 1;
    if (j2534.PassThruWriteMsgs(chanID, &txmsg, &numTxMsg, 1000))
    {
        reportJ2534Error();
    }
    else
    {
        printf("RPM request sent to instrument cluster.\n");
    }

        Sleep(2000);  // Wait for 2 seconds instead of 500 ms

// Read RPM response
PASSTHRU_MSG rxmsg;
unsigned long numRxMsg = 1;
long status = j2534.PassThruReadMsgs(chanID, &rxmsg, &numRxMsg, 1000);
if (status == 0 && numRxMsg > 0)
{
    // Check if it's an RPM response
    if(rxmsg.Data[1] == 0x62 && rxmsg.Data[2] == 0x22 && rxmsg.Data[3] == 0xD1) 
    {
        unsigned int rpmValue = (rxmsg.Data[4] << 8) + rxmsg.Data[5];
        unsigned int rpmActual = rpmValue / 4;
        printf("Received RPM: %d\n", rpmActual);
    }
    else 
    {
        printf("Received unrecognized response.\n");
    }
}
else if (status != 0)
{
    printf("Error reading response. J2534 Status: %ld\n", status);
    reportJ2534Error();
}
else
{
    printf("No response received from the instrument cluster.\n");
}

// Cleanup
if (j2534.PassThruDisconnect(chanID))
{
    reportJ2534Error();
}

if (j2534.PassThruClose(devID))
{
    reportJ2534Error();
}

return 0;
}

Console Log is following:

RPM request sent to instrument cluster.
Error reading response. J2534 Status: 16
J2534 error [no data was read].

Process returned 0 (0x0)   execution time : 3.084 s
Press any key to continue.

Where I am trying following:

  1. Initialize the J2534 device.
  2. Connect to the protocol, which in this case is CAN.
  3. Set the appropriate message filter to listen to the responses from the ECU.
  4. Send the RPM request.
  5. Wait and read the response.
  6. Decode the RPM value from the response.
  7. Clean up (disconnect and close).

Code number 2 is this:

#include <iostream>
#include <windows.h>
#include "J2534.h"

// Function to report J2534 errors
void reportJ2534Error(J2534 &j2534) {
    char err[512];
    j2534.PassThruGetLastError(err);
    printf("J2534 error [%s].\n", err);
}

int main() {
    J2534 j2534;

    // Initialize the J2534 DLL
    if (!j2534.init()) {
        printf("Can't connect to J2534 DLL.\n");
        return 0;
    }

    unsigned long devID;
    unsigned long chanID;

    // Open and connect to the device
    if (j2534.PassThruOpen(NULL, &devID)) {
        reportJ2534Error(j2534);
        return 0;
    }

    if (j2534.PassThruConnect(devID, CAN, 0, 500000, &chanID)) {
        reportJ2534Error(j2534);
        return 0;
    }

    // Set up a filter for CAN ID 0x77E (the expected response ID)
    PASSTHRU_MSG msgMask, msgPattern;
    unsigned long msgId;
    msgMask.ProtocolID = CAN;
    msgMask.DataSize = 4;
    memset(msgMask.Data, 0xFF, 4);
    msgPattern.ProtocolID = CAN;
    msgPattern.DataSize = 4;
    msgPattern.Data[2] = 0x07;
    msgPattern.Data[3] = 0x7E;
    if (j2534.PassThruStartMsgFilter(chanID, PASS_FILTER, &msgMask, &msgPattern, NULL, &msgId)) {
        reportJ2534Error(j2534);
        return 0;
    }

    // Send RPM request
    PASSTHRU_MSG txmsg;
    txmsg.ProtocolID = CAN;
    txmsg.RxStatus = 0;
    txmsg.TxFlags = 0;
    txmsg.DataSize = 8;
    txmsg.Data[0] = 0x03;  // Length of the following message
    txmsg.Data[1] = 0x22;
    txmsg.Data[2] = 0x22;
    txmsg.Data[3] = 0xD1;
    txmsg.Data[4] = 0x55;
    txmsg.Data[5] = 0x55;
    txmsg.Data[6] = 0x55;
    txmsg.Data[7] = 0x55;

    unsigned long numTxMsg = 1;
    if (j2534.PassThruWriteMsgs(chanID, &txmsg, &numTxMsg, 1000)) {
        reportJ2534Error(j2534);
    } else {
        printf("RPM request sent to instrument cluster.\n");
    }

    // Continuously poll for the RPM response for a few seconds
    PASSTHRU_MSG rxmsg;
    unsigned long numRxMsg;
    int attempts = 10;
    bool responseReceived = false;

    while (attempts--) {
        numRxMsg = 1;
        if (j2534.PassThruReadMsgs(chanID, &rxmsg, &numRxMsg, 1000) == 0 && numRxMsg > 0) {
            printf("Received response: ");
            for (unsigned int i = 0; i < rxmsg.DataSize; i++) {
                printf("%02X ", rxmsg.Data[i]);
            }
            printf("\n");
            responseReceived = true;
            break;
        }
        Sleep(300);  // Wait for 300ms before the next attempt
    }

    if (!responseReceived) {
        printf("No RPM response received from the instrument cluster.\n");
    }

    // Cleanup: Disconnect and close the device
    if (j2534.PassThruDisconnect(chanID)) {
        reportJ2534Error(j2534);
    }

    if (j2534.PassThruClose(devID)) {
        reportJ2534Error(j2534);
    }

    return 0;
}

This program initializes the J2534 connection, sets up a filter for the expected ECU response, sends an RPM request, and continuously polls for a response for a few seconds. If a response is received, it prints it; otherwise, it indicates that no response was received.

As you would expect I am getting indication that no response is received.

Has anyone faced a similar issue or can guide me on what might I be doing wrong?

0

There are 0 best solutions below