Trying to detect DTC (error codes) with OBD2 and HC05

I am changing the instrument gauge of my car to an older version which does not support CAN protocol on its instrument gauge. But I wanted to see if a DTC or error codes ever comes which usually lights up a Malfuction indicator lamp (check engine light, EPS, immobiliser, temperature etc.). I am planning to use an arduino for that. I have a OBD2 connector which sends data over bluetooth, for that i also have an HC05 module to recieve data and send to arduino.
I figured out the wiring and connected to the module using the library ELMdunio and I was able to recieve data like rpm on the serial monitor.
But I couldn't figure out a way to detect DTCs.
Could any help me find out the code?

This?

https://www.arduino.cc/reference/en/libraries/elmduino/

Did you check out the documentation:

yes, this is it. Yes, i looked at the documentation.
In

List of Supported OBD PID Processing Functions:

uint16_t freezeDTC();

I saw this line but don't know what it means

Actually, I really dont need to know what the specific codes are. But I just want to know whether any code is present. Just to switch on and off a Relay.

I've never checked or cleared error codes before, but this might help:

Following is a code generated by chatgtp, but after lot of iterations it does not tell if a DTC is present.
It shows no DTC present, but there is one. Yes, I checked with an app too.
Could anyone show where it went wrong? I just cant figure it out.

#include <SoftwareSerial.h>
#include <ELMduino.h>

// Define the HC-05 module pins
const int bluetoothRxPin = 2; // RX pin of HC-05 connected to Arduino pin 2
const int bluetoothTxPin = 3; // TX pin of HC-05 connected to Arduino pin 3

// Create a SoftwareSerial object to communicate with HC-05
SoftwareSerial bluetoothSerial(bluetoothRxPin, bluetoothTxPin);

// Create an instance of ELM327 class
ELM327 myELM327;

void setup() {
  // Start serial communication with your computer
  Serial.begin(9600);

  // Start communication with the HC-05 module
  bluetoothSerial.begin(38400);

  // Initialize ELM327
  myELM327.begin(bluetoothSerial);

  // Reset ELM327 and set protocol to automatic
  myELM327.sendCommand("ATZ");
  myELM327.sendCommand("ATSP0");
}

void loop() {
  // Request the number of DTCs
  myELM327.sendCommand("01 01");

  // Read the response
  int8_t* responseBytes = myELM327.get_response();

  // Convert the response bytes to a string
  String response = "";
  for (int i = 0; responseBytes[i] != 0x00; i++) {
    response += char(responseBytes[i]);
  }

  // Extract the number of DTCs from the response
  int numDTCs = response.charAt(5) & 0x7F;

  // Check if there are any DTCs
  if (numDTCs > 0) {
    // Request the actual trouble codes
    myELM327.sendCommand("01");

    // Read the response
    int8_t* dtcResponseBytes = myELM327.get_response();

    // Convert the DTC response bytes to a string
    String dtcResponse = "";
    for (int i = 0; dtcResponseBytes[i] != 0x00; i++) {
      dtcResponse += char(dtcResponseBytes[i]);
    }

    // Print the DTCs
    Serial.println("Diagnostic Trouble Codes:");
    for (int i = 0; i < numDTCs; i++) {
      String dtc = dtcResponse.substring(6 + i * 6, 8 + i * 6);
      Serial.println("DTC " + String(i + 1) + ": " + dtc);
    }
  } else {
    Serial.println("No Diagnostic Trouble Codes found.");
  }

  // Delay before the next loop
  delay(5000);
}


Following is a code generated by chatgtp

That's a mistake. Don't use ChatGPT for anything beyond getting brief overviews of a subject or paper.

Did you look at the link I posted previously?

Yes, understood the logic behind it that request PID 01 01 and we will recieve a response and should select the byte (hex) containing number of DTCs and subtract 80 from it and will get number of DTCs.
But the thing is, I dont know how to call functions and request PIDs and read the responses. Thats why I turned to ChatGTP, and it was not great at this.
Could you help with this please?

Could you help with an example on how to use this OBD PID processing function from your ELMduino Library?

uint32_t monitorStatus();
I wanted to know how we could send PID request and see them on the serial monitor.

Really I do appreciate the effort taken to put up this library. Thank you.

Serial.println(myELM327.monitorstatus());

This gave me output of -
24576

I couldnt find any thing to relate to.

This is the code that I used, I modified a different code from a YouTube video.
This works for me.


#include<SoftwareSerial.h>
#include <ELMduino.h>


SoftwareSerial BTSerial(2,3); 
char incomingbyte = '-'; 
int relay=6;
char bufOut[40];

#define ELM_PORT BTSerial
ELM327 myELM327;



void setup() {
  
 pinMode(relay, OUTPUT);
 digitalWrite(6,HIGH);
  Serial.begin(9600);  
  BTSerial.begin(9600); 
  
  ELM_PORT.begin(9600);
   myELM327.begin(BTSerial);
    while(!myELM327.begin(ELM_PORT))
  {
    
    Serial.println("Couldn't connect to OBD scanner");
        digitalWrite(6,HIGH);
        delay(1500);
        digitalWrite(6,LOW);
        delay(1500);
  }

  Serial.println("Connected to ELM327");

}

void loop()
{
  int i = 0;
  int rpm=0;
  char bufOutrpm[40];
  

  for(int j=0; j<39; j++) 
  bufOutrpm[j]='-';
  delay(200);
    
  BTSerial.flush();
  BTSerial.print("01 0C\r"); 
  
  
  while(incomingbyte !='>') 
  {
    while (BTSerial.available() > 0) 
    {
      incomingbyte = BTSerial.read();
      bufOutrpm[i++] = incomingbyte;
      if (i >37) break;
    
    }

    
  }
  bufOutrpm[i++]='\0';
  BTSerial.flush();
  incomingbyte ='-';  
  
  for(int j=0; bufOutrpm[j]!='>'; j++)
  {
    if(((bufOutrpm[j]=='0' && bufOutrpm[j+1]=='0' && bufOutrpm[j+2]=='0' && bufOutrpm[j+3]=='0') || (bufOutrpm[j]=='0' && bufOutrpm[j+1]=='0' && bufOutrpm[j+2]==' ' && bufOutrpm[j+3]=='0' && bufOut[j+4]=='0')))
    {
      rpm++;
    }
  }
  
  Serial.println(bufOutrpm);


if(rpm!=0)
{
  digitalWrite(6,HIGH);
}

else
{
  i = 0;
  char bufOut[40];
  

  for(int j=0; j<39; j++) bufOut[j]='-';
  delay(200);
    
  BTSerial.flush();
  BTSerial.print("01 01\r"); 
  
  
  while(incomingbyte !='>') 
  {
    while (BTSerial.available() > 0) 
    {
      incomingbyte = BTSerial.read();
      bufOut[i++] = incomingbyte;
      if (i >37) break;
    // Serial.println(incomingbyte);
    // Serial.println("Recieving Data");
    }

    
  }
  bufOut[i++]='\0';
  BTSerial.flush();
  incomingbyte ='-';  
  
  Serial.println(bufOut);
  
  int dtc=0;
  int count=0;

 for(int j=0; bufOut[j]!='>'; j++)
 {
   if((bufOut[j]=='0' && bufOut[j+1]=='1' && bufOut[j+2]=='0' && bufOut[j+3]=='0') || (bufOut[j]=='0' && bufOut[j+1]=='1' && bufOut[j+2]==' ' && bufOut[j+3]=='0' && bufOut[j+4]=='0'))
      {
        dtc=0;
      }
   else{
     dtc++;
     count=j;
   }
 }
      if(dtc<count)
      {
      
               Serial.println("NO DTCs");
               digitalWrite(6,LOW);
      }
   else
          {
          Serial.println("DTC Found");
          digitalWrite(6,HIGH);
          }
  
    
  delay(1500);
  
}
}

Hi man, I have seen you developed ELMduino library, right? Is it possible to put the PID command A6 to read odometer's value there?

Yes according to this website https://en.wikipedia.org/wiki/OBD-II_PIDs , Service mode 1, PID request A6 will return a set of 4 bytes of hexadecimal data, which can be converted to decimal and applied the formula could give you odometer reading.

But this may not work on every car. Depends on the car.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.