Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for non-standard PIDs #4

Closed
miguelos6 opened this issue Feb 14, 2020 · 39 comments
Closed

support for non-standard PIDs #4

miguelos6 opened this issue Feb 14, 2020 · 39 comments
Assignees
Labels
enhancement New feature or request

Comments

@miguelos6
Copy link

Please add support for non-standard PIDs, for example the ones from Opel mentioned here
https://www.club-opel.com/forum-tema/pid-kody-pro-obd2-165356

@PowerBroker2 PowerBroker2 self-assigned this Feb 15, 2020
@PowerBroker2
Copy link
Owner

Can you provide an example query and response? i.e.:

Query: 2223AD
Response: 2223AD AE34>

I ask this because custom PIDs depend on the make/model of cars and I don't have an Opel to test on. If you send me your test results I can incorporate the functionality into the library much easier.

@miguelos6
Copy link
Author

is there any easy way to dump it from Bluetooth ?

@PowerBroker2
Copy link
Owner

If you have an android or laptop with bluetooth, you can use a BT Serial app to connect and communicate with the ELM327. I use my laptop with Bluetooth Serial Terminal. Then you can use copy and paste or take a screenshot.

@PowerBroker2
Copy link
Owner

On second thought, you can use this instead to access the ELM327 through the Serial Monitor without a third party app:

#include "BluetoothSerial.h"


BluetoothSerial SerialBT;


#define DEBUG_PORT Serial
#define ELM_PORT   SerialBT


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  DEBUG_PORT.begin(115200);
  ELM_PORT.begin("ESP32test", true);

  DEBUG_PORT.println("Attempting to connect to ELM327...");

  if (!ELM_PORT.connect("OBDII"))
  {
    DEBUG_PORT.println("Couldn't connect to OBD scanner");
    while(1);
  }

  DEBUG_PORT.println("Connected to ELM327");
  DEBUG_PORT.println("Ensure your serial monitor line ending is set to 'Carriage Return'");
  DEBUG_PORT.println("Type and send commands/queries to your ELM327 through the serial monitor");
  DEBUG_PORT.println();
}


void loop()
{
  if(DEBUG_PORT.available())
  {
    char c = DEBUG_PORT.read();

    DEBUG_PORT.write(c);
    ELM_PORT.write(c);
  }

  if(ELM_PORT.available())
  {
    char c = ELM_PORT.read();

    if(c == '>')
      DEBUG_PORT.println();

    DEBUG_PORT.write(c);
  }
}

@miguelos6
Copy link
Author

Hi
I managed to connect using code you mentioned

`Attempting to connect to ELM327...
ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac
Attempting to connect to ELM327...
Connected to ELM327
Ensure your serial monitor line ending is set to 'Carriage Return'
Type and send commands/queries to your ELM327 through the serial monitor

2223AD
6223AD5B32

2220FA
6220FA00

2220F2
6220F200

22336A
62336A49

22132a
62132A09FF

22132A
62132A09FE

223039
623039019F

`

I'm not sure how to convert these, but in Torque I'm using the following :
PID 223039 // km since last regeneration // equation A256+B // OBD Header to use 7E0
PID 22336A // DFP soot level % // equation A // OBD Header to use 7E0
PID 2220F2 // DFP burn status // equation A // unit type on/off // OBD Header to use 7E0
PID 22132A // fuel litres left // equation (A
256+B)/64 // OBD Header 7E0

@PowerBroker2
Copy link
Owner

PowerBroker2 commented Feb 26, 2020

Ok, cool - now that I have the example queries, I can walk through how to decode/understand the responses and integrate them into the library. Here are the response explanations:

Query: 0x2223AD
Service: 0x22
PID: 0x23AD
Response Header: 0x6223AD
A: 0x5B = 91
B: 0x32 = 50
???? (Parameter and equation not given)

Query: 0x2220FA
Service: 0x22
PID: 0x20FA
Response Header: 0x6220FA
A: 0x0 = 0
???? (Parameter and equation not given)

Query: 0x2220F2
Service: 0x22
PID: 0x20F2
Response Header: 0x6220F2
A: 0x0 = 0
DFP burn status = A = 0 = Off

Query: 0x22336A
Service: 0x22
PID: 0x336A
Response Header: 0x62336A
A: 0x49 = 73
DFP soot level % = A = 73 %

Query: 0x22132A
Service: 0x22
PID: 0x132A
Response Header: 0x62132A
A: 0x09 = 9
B: 0xFF = 255
Fuel liters left = ((A * 256) + B) / 64 = ((9 * 256) + 255) / 64 = 39.984375 Liters

Query: 0x223039
Service: 0x22
PID: 0x3039
Response Header: 0x623039
A: 0x01 = 1
B: 0x9F = 159
Km since last regeneration = (A * 256) + B = (1 * 256) + 159 = 415 Km

@PowerBroker2
Copy link
Owner

I'll update the library sometime in the next couple of weeks or so (as my free time permits, lol)

@miguelos6
Copy link
Author

miguelos6 commented Feb 26, 2020

thanks! that's exactly the values I could read using Torque
Having these will solve my problems :) working on solution on Wemos lolin (OLED display)

I guess if this proves to be working well it may need small instructions on how to extend it for other PIDs and will have variety of uses

@miguelos6
Copy link
Author

miguelos6 commented Feb 26, 2020

Hi, I'm not good at it, but was trying to understand how it works
Could it possibly be something similar to this :

// my custom code starts here .h file
const uint8_t SERVICE_22 = 34; // 0x22 - Ford/GM
const uint8_t OP_DPF_BURN = 8434; // 0x20F2 - bit encoded
const uint8_t OP_DPF_PERCENT = 13162; // 0x336A - %
const uint8_t OP_DPF_DISTANCE = 12345; // 0x3039 - km
const uint8_t OP_FUEL_TANK_LITRES = 4906; // 0x132A - L
// my custom code ends here .h file

// my custom code starts here .CPP file
float ELM327::dpfburn()
{
if (queryPID(SERVICE_22, OP_DPF_BURN))
return findResponse(true);

return ELM_GENERAL_ERROR;

}

float ELM327::dpfpercent()
{
if (queryPID(SERVICE_22, OP_DPF_PERCENT))
return findResponse(true);

return ELM_GENERAL_ERROR;

}

float ELM327::dpfdistance()
{
if (queryPID(SERVICE_22, OP_DPF_DISTANCE))
return findResponse(true);
// don't know how to calcuate A and B here
return ELM_GENERAL_ERROR;
}

float ELM327::fueltanklitres()
{
if (queryPID(SERVICE_22, OP_FUEL_TANK_LITRES))
return findResponse(true);
// don't know how to calcuate A and B here
return ELM_GENERAL_ERROR;
}

// my custom code ends here .CPP file

@PowerBroker2
Copy link
Owner

While testing your code is useless because the library doesn't support custom PID queries yet. That being said, you have the right idea. You'll pass the desired service and PID to queryPID() and it will return a 16-bit unsigned int (containing response parts A and B) that you can then use to calculate the value you need.

That being said, I don't plan on incorporating any constants into the library's header file since there's no guarantee that such values are valid or supported for all makes/models.

I'll let you know once the changes to the library is made.

@miguelos6
Copy link
Author

sure, I was just trying to understand how it works (didn't test though)
I'd appreciate anything that would lead to desired outcome and will wait for any suggestion when you find time

@PowerBroker2
Copy link
Owner

Should be fixed in release 2.0.0. Let me know if it works for you or not!

@PowerBroker2 PowerBroker2 added the enhancement New feature or request label Feb 28, 2020
@miguelos6
Copy link
Author

miguelos6 commented Feb 28, 2020

Thank you for 2.0.0 version!

Could you please guide me on how to use queries purely in my main sketch ?

For now, by comparing the code I created another functions (?) for my purpose in ELMduino.cpp, like below :

// miguel test SOOT %
float ELM327::dpfsoot()
{
if (queryPID(34, 13162))
// service & PID are in int values
return (findResponse());

return ELM_GENERAL_ERROR;
}

and did everything similarly like you did for rpm query, modifying it accordingly
Still I get 0 values everywhere (same as example rpm), as mentioned here : #3

How should I calculate when 4 hex digit values are returned ?
Sorry for my ignorance, I'm not an programmer ;/

@PowerBroker2
Copy link
Owner

PowerBroker2 commented Feb 28, 2020

You don't need to add any functions to the library. Honestly, I would advise against it since any updates to the library will overwrite your edits. It's easier to create functions for finding these custom values in your sketch. You can do this because both queryPID() and findResponse() are public members of the ELM327 class:

int16_t soot = -1;
if (myELM327.queryPID(34, 13162))
	soot = myELM327.findResponse();

Assuming the service and PID numbers are accurate, this will work for all responses regardless of length (i.e. 2 hex digit responses vs 4 hex digit responses). The library packages all available hex digits from the response data and combines them into an unsigned 32 bit number. If only 16 bits of data (2 hex digits) exists in the response, the MSB (Most Significant Byte) is left zeroed out.

The only thing you have to worry about is when scaling is needed. For instance, you might need to implement the following:

float litersLeft = -1;
if (myELM327.queryPID(34, 4906))
	litersLeft = myELM327.findResponse() / 64.0;

@miguelos6
Copy link
Author

miguelos6 commented Feb 29, 2020

Hi, I've just tried and got success only for standard rpm from ESP32 example
While adding code according to your suggestions the values is read just once, then everything is zeroed out. Please check code & my addons

// modified test + my custom PIDs
// based purely on library

#include "BluetoothSerial.h"
#include "ELMduino.h"


#define ELM_PORT SerialBT
#define ESP_BLUETOOTH_NAME "ESP32"


BluetoothSerial SerialBT;
ELM327 myELM327;


uint32_t rpm = 0;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);

  Serial.println("Attempting to connect to ELM327...");

  if (!ELM_PORT.connect("V-LINK"))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 1");
    while (1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }
  
  Serial.println("Connected to ELM327");
  // blink fast 10 times
      for (int a = 0; a < 10; ++a) {
      digitalWrite(LED_BUILTIN,HIGH); delay(100);
      digitalWrite(LED_BUILTIN,LOW); delay(100); 
      }  
  
}


void loop()
{
  float tempRPM = myELM327.rpm();
  int16_t soot = -1;
  int16_t burn = -1;
  float litersLeft = -1;
    
  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (uint32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
    delay(200);
    
    if (myELM327.queryPID(34, 13162)) {
      soot = myELM327.findResponse();
      Serial.print("soot: "); Serial.println(soot);
      delay(200);
    }

    if (myELM327.queryPID(34, 4906)) {
      litersLeft = myELM327.findResponse() / 64.0;    
      Serial.print("liters: "); Serial.println(litersLeft);
      delay(200);
    }

    if (myELM327.queryPID(34, 8434)) {
      burn = myELM327.findResponse();    
      Serial.print("DPF burns: "); Serial.println(burn);
      delay(200);
    }

// loop ends - blink slowly 5 times
      for (int a = 0; a < 5; ++a) {
      digitalWrite(LED_BUILTIN,HIGH); delay(200);
      digitalWrite(LED_BUILTIN,LOW); delay(200); 
      }  
    
  }
  else
  {
    Serial.print(F("\tERROR: "));
    Serial.println(myELM327.status);
    delay(100);
  }
}

and output it produces :

09:16:31.900 -> ⸮⸮Attempting to connect to ELM327...
09:16:57.701 -> Connected to ELM327
09:16:59.860 -> ERROR: 7
09:17:00.007 -> ERROR: 6
09:17:00.267 -> ERROR: 7
09:17:00.489 -> ERROR: 7
09:17:00.746 -> ERROR: 7
09:17:00.933 -> RPM: 1048
09:17:01.229 -> soot: 0
09:17:01.451 -> liters: 0.00
09:17:01.706 -> DPF burns: 0
09:17:03.932 -> RPM: 0
09:17:04.186 -> soot: 0
09:17:04.442 -> liters: 0.00
09:17:04.661 -> DPF burns: 0
09:17:06.912 -> RPM: 0
09:17:07.131 -> soot: 0
09:17:07.383 -> liters: 0.00
09:17:07.608 -> DPF burns: 0
09:17:09.867 -> RPM: 0
09:17:10.123 -> soot: 0
09:17:10.340 -> liters: 0.00
09:17:10.596 -> DPF burns: 0

Is it something not properly cleared by findResponse or queryPID ?
how should querying for more different values look like within a loop ?

@PowerBroker2
Copy link
Owner

Try this and see what it says:

// modified test + my custom PIDs
// based purely on library

#include "BluetoothSerial.h"
#include "ELMduino.h"


#define ELM_PORT SerialBT
#define ESP_BLUETOOTH_NAME "ESP32"


BluetoothSerial SerialBT;
ELM327 myELM327;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);

  Serial.println("Attempting to connect to ELM327...");

  if (!ELM_PORT.connect("V-LINK"))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 1");
    while (1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }
  
  Serial.println("Connected to ELM327");
  
  for (int a = 0; a < 10; ++a)
  {
    digitalWrite(LED_BUILTIN,HIGH); delay(100);
    digitalWrite(LED_BUILTIN,LOW); delay(100); 
  }
}


void loop()
{
  int32_t rpm = -1;
  int32_t soot = -1;
  int32_t burn = -1;
  float litersLeft = -1;

  float tempRPM = myELM327.rpm();
  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (int32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else
      printError();

  if (myELM327.queryPID(34, 13162))
  {
    int32_t tempSoot = myELM327.findResponse();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      soot = tempSoot;
      Serial.print("DPF burns: "); Serial.println(soot);
    }
    else
      printError();
  }

  if (myELM327.queryPID(34, 4906))
  {
    int32_t tempLitersLeft = myELM327.findResponse() / 64.0;    

    if (myELM327.status == ELM_SUCCESS)
    {
      litersLeft = tempLitersLeft;
      Serial.print("Liters: "); Serial.println(litersLeft);
    }
    else
      printError();
  }

  if (myELM327.queryPID(34, 8434))
  {
    int32_t tempBurn = myELM327.findResponse();

    if (myELM327.status == ELM_SUCCESS)
    {
      burn = tempBurn;
      Serial.print("DPF burns: "); Serial.println(burn);
    }
    else
      printError();
  }

  for (int a = 0; a < 5; ++a)
  {
    digitalWrite(LED_BUILTIN,HIGH); delay(200);
    digitalWrite(LED_BUILTIN,LOW); delay(200); 
  }
}


void printError()
{
  Serial.print("Received: ");
  for (byte i = 0; i < PAYLOAD_LEN; i++)
    Serial.write(myELM327.payload[i]);
  Serial.println();
  
  switch (myELM327.status)
  {
    case ELM_SUCCESS:
    {
      Serial.println(F("\tELM_SUCCESS"));
    }
    case ELM_NO_RESPONSE:
    {
      Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
    }
    case ELM_BUFFER_OVERFLOW:
    {
      Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
    }
    case ELM_GARBAGE:
    {
      Serial.println(F("\tERROR: ELM_GARBAGE"));
    }
    case ELM_UNABLE_TO_CONNECT:
    {
      Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
    }
    case ELM_NO_DATA:
    {
      Serial.println(F("\tERROR: ELM_NO_DATA"));
    }
    case ELM_STOPPED:
    {
      Serial.println(F("\tERROR: ELM_STOPPED"));
    }
    case ELM_TIMEOUT:
    {
      Serial.println(F("\tERROR: ELM_TIMEOUT"));
    }
    case ELM_GENERAL_ERROR:
    {
      Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));
    }
  }

  delay(100);
}

@miguelos6
Copy link
Author

miguelos6 commented Mar 2, 2020

I tried your code, and it zeroes out values since the first run :

08:12:04.978 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
08:12:04.978 -> configsip: 0, SPIWP:0xee
08:12:04.978 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
08:12:05.016 -> mode:DIO, clock div:1
08:12:05.016 -> load:0x3fff0018,len:4
08:12:05.016 -> load:0x3fff001c,len:1044
08:12:05.016 -> load:0x40078000,len:8896
08:12:05.016 -> load:0x40080400,len:5816
08:12:05.016 -> entry 0x400806ac
08:12:05.784 -> Attempting to connect to ELM327...
08:12:30.773 -> Connected to ELM327
08:12:32.913 -> Received: SEARCHING...
08:12:32.913 -> 	ERROR: ELM_TIMEOUT
08:12:32.913 -> 	ERROR: ELM_GENERAL_ERROR
08:12:33.050 -> Received: 
08:12:33.083 -> 	ERROR: ELM_STOPPED
08:12:33.083 -> 	ERROR: ELM_TIMEOUT
08:12:33.083 -> 	ERROR: ELM_GENERAL_ERROR
08:12:33.193 -> Liters: 0.00
08:12:33.230 -> DPF burns: 0
08:12:35.352 -> RPM: 0
08:12:35.352 -> DPF burns: 0
08:12:35.352 -> Liters: 0.00
08:12:35.402 -> DPF burns: 0

when I comment out all but rpm it works :

08:19:21.252 -> Attempting to connect to ELM327...
08:19:46.327 -> Connected to ELM327
08:19:48.478 -> Received: SEARCHING...
08:19:48.478 -> 	ERROR: ELM_TIMEOUT
08:19:48.513 -> 	ERROR: ELM_GENERAL_ERROR
08:19:50.721 -> Received: 410C0E0D
08:19:50.757 -> 	ERROR: ELM_TIMEOUT
08:19:50.757 -> 	ERROR: ELM_GENERAL_ERROR
08:19:52.982 -> Received: 410C125C
08:19:52.982 -> 	ERROR: ELM_TIMEOUT
08:19:52.982 -> 	ERROR: ELM_GENERAL_ERROR
08:19:55.362 -> Received: 410C0C3A
08:19:55.362 -> 	ERROR: ELM_TIMEOUT
08:19:55.362 -> 	ERROR: ELM_GENERAL_ERROR
08:19:57.501 -> Received: 410C0BDB
08:19:57.501 -> 	ERROR: ELM_TIMEOUT
08:19:57.501 -> 	ERROR: ELM_GENERAL_ERROR
08:19:59.703 -> RPM: 809
08:20:01.775 -> RPM: 1361
08:20:03.892 -> RPM: 1195
08:20:05.984 -> RPM: 761
08:20:08.067 -> RPM: 1629
08:20:10.170 -> RPM: 770
08:20:12.311 -> RPM: 758

so I tried commenting out rpm and running just first custom query (soot, we should get result within range 0-100, it just prints wrong description, not as the name suggests - burn is 0/1) :

08:22:44.375 -> ⸮Attempting to connect to ELM327...
08:23:09.998 -> Connected to ELM327
08:23:12.156 -> Received: SEARCHING...
08:23:12.156 -> 	ERROR: ELM_TIMEOUT
08:23:12.156 -> 	ERROR: ELM_GENERAL_ERROR
08:23:12.294 -> Received: 
08:23:12.294 -> 	ERROR: ELM_STOPPED
08:23:12.294 -> 	ERROR: ELM_TIMEOUT
08:23:12.294 -> 	ERROR: ELM_GENERAL_ERROR
08:23:14.465 -> DPF burns: 0
08:23:16.525 -> DPF burns: 0
08:23:18.630 -> DPF burns: 0
08:23:20.701 -> DPF burns: 0
08:23:22.779 -> DPF burns: 0
08:23:24.870 -> DPF burns: 0

looks like there is something that zeroes the query result?

@PowerBroker2
Copy link
Owner

PowerBroker2 commented Mar 2, 2020

What seems to be happening is that the header for the query responses aren't being found. If this happens, findResponse() returns 0 and that's what you're seeing here. The big things to ensure are that the response header in findResponse() is formed correctly and the ELM327 is returning responses with the correct header.

For now, please try this new sketch:

// modified test + my custom PIDs
// based purely on library

#include "BluetoothSerial.h"
#include "ELMduino.h"


#define ELM_PORT SerialBT
#define ESP_BLUETOOTH_NAME "ESP32"


BluetoothSerial SerialBT;
ELM327 myELM327;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);

  Serial.println("Attempting to connect to ELM327...");

  if (!ELM_PORT.connect("V-LINK"))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 1");
    while (1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }
  
  Serial.println("Connected to ELM327");
  
  for (int a = 0; a < 10; ++a)
  {
    digitalWrite(LED_BUILTIN,HIGH); delay(100);
    digitalWrite(LED_BUILTIN,LOW); delay(100); 
  }
}


void loop()
{
  int32_t rpm = -1;
  int32_t soot = -1;
  int32_t burn = -1;
  float litersLeft = -1;

  /////////////////////////////////////////////////////// RPM
  float tempRPM = myELM327.rpm();
  
  Serial.print("Payload received for rpm: ");
  for (byte i = 0; i < PAYLOAD_LEN; i++)
    Serial.write(myELM327.payload[i]);
  Serial.println();
  
  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (int32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else
      printError();

  /////////////////////////////////////////////////////// Soot
  if (myELM327.queryPID(34, 13162))
  {
    int32_t tempSoot = myELM327.findResponse();

    Serial.print("Payload received for soot: ");
    for (byte i = 0; i < PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      soot = tempSoot;
      Serial.print("Soot: "); Serial.println(soot);
    }
    else
      printError();
  }

  /////////////////////////////////////////////////////// Liters
  if (myELM327.queryPID(34, 4906))
  {
    int32_t tempLitersLeft = myELM327.findResponse() / 64.0;

    Serial.print("Payload received for liters: ");
    for (byte i = 0; i < PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();

    if (myELM327.status == ELM_SUCCESS)
    {
      litersLeft = tempLitersLeft;
      Serial.print("Liters: "); Serial.println(litersLeft);
    }
    else
      printError();
  }

  /////////////////////////////////////////////////////// Burns
  if (myELM327.queryPID(34, 8434))
  {
    int32_t tempBurn = myELM327.findResponse();

    Serial.print("Payload received for DPF burns: ");
    for (byte i = 0; i < PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();

    if (myELM327.status == ELM_SUCCESS)
    {
      burn = tempBurn;
      Serial.print("DPF burns: "); Serial.println(burn);
    }
    else
      printError();
  }

  for (int a = 0; a < 5; ++a)
  {
    digitalWrite(LED_BUILTIN,HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN,LOW);
    delay(200); 
  }
}


void printError()
{
  if (myELM327.status == ELM_SUCCESS)
    Serial.println(F("\tELM_SUCCESS"));
  else if (myELM327.status == ELM_NO_RESPONSE)
    Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
  else if (myELM327.status == ELM_BUFFER_OVERFLOW)
    Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
  else if (myELM327.status == ELM_GARBAGE)
    Serial.println(F("\tERROR: ELM_GARBAGE"));
  else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
    Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
  else if (myELM327.status == ELM_NO_DATA)
    Serial.println(F("\tERROR: ELM_NO_DATA"));
  else if (myELM327.status == ELM_STOPPED)
    Serial.println(F("\tERROR: ELM_STOPPED"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_TIMEOUT"));
  else if (myELM327.status == ELM_GENERAL_ERROR)
    Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));
  }

  delay(500);
}

@PowerBroker2
Copy link
Owner

Also, I just made a small edit to the library that should make things run a little better in release 2.0.1. Please try the above sketch with the new release.

@PowerBroker2
Copy link
Owner

Ok, so I wrote a quick ELM327 emulator in Python to do some "live" testing of the custom PIDs. Turns out there was a bug in how I was converting the decimal values of the query's service and PID numbers to hex. I fixed the bug in release 2.0.2. Let me know if it solves your problem.

@miguelos6
Copy link
Author

Hi, I tested your modified code, here are the results
looks like sth with calculations ?

21:15:26.849 -> ets Jun  8 2016 00:22:57
21:15:26.879 -> 
21:15:26.879 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
21:15:26.879 -> configsip: 0, SPIWP:0xee
21:15:26.879 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
21:15:26.879 -> mode:DIO, clock div:1
21:15:26.879 -> load:0x3fff0018,len:4
21:15:26.879 -> load:0x3fff001c,len:1044
21:15:26.879 -> load:0x40078000,len:8896
21:15:26.879 -> load:0x40080400,len:5816
21:15:26.879 -> entry 0x400806ac
21:15:27.644 -> Attempting to connect to ELM327...
21:15:53.574 -> Connected to ELM327
21:15:55.707 -> Payload received for rpm: SEARCHING...
21:15:55.707 -> 	ERROR: ELM_TIMEOUT
21:15:56.372 -> Payload received for soot: 62336A36
21:15:56.372 -> 	ERROR: ELM_TIMEOUT
21:15:57.001 -> Payload received for liters: 62132A05D3
21:15:57.001 -> 	ERROR: ELM_TIMEOUT
21:15:57.659 -> Payload received for DPF burns: 6220F200
21:15:57.659 -> 	ERROR: ELM_TIMEOUT
21:16:00.266 -> Payload received for rpm: 410C10A4
21:16:00.266 -> RPM: 1065
21:16:00.374 -> Payload received for soot: 62336A36
21:16:00.374 -> Soot: 0
21:16:00.447 -> Payload received for liters: 62132A05D3
21:16:00.447 -> Liters: 0.00
21:16:00.554 -> Payload received for DPF burns: 6220F200
21:16:00.554 -> DPF burns: 0
21:16:02.644 -> Payload received for rpm: 410C1098
21:16:02.644 -> RPM: 1062
21:16:02.752 -> Payload received for soot: 62336A36
21:16:02.752 -> Soot: 0
21:16:02.858 -> Payload received for liters: 62132A05D2
21:16:02.858 -> Liters: 0.00
21:16:02.931 -> Payload received for DPF burns: 6220F200
21:16:02.968 -> DPF burns: 0
21:16:05.063 -> Payload received for rpm: 410C104C
21:16:05.063 -> RPM: 1043
21:16:05.132 -> Payload received for soot: 62336A36
21:16:05.132 -> Soot: 0
21:16:05.243 -> Payload received for liters: 62132A05D2
21:16:05.243 -> Liters: 0.00
21:16:05.312 -> Payload received for DPF burns: 6220F200
21:16:05.312 -> DPF burns: 0
21:16:07.403 -> Payload received for rpm: 410C139C
21:16:07.403 -> RPM: 1255
21:16:07.474 -> Payload received for soot: 62336A36
21:16:07.474 -> Soot: 0
21:16:07.547 -> Payload received for liters: 62132A05D2
21:16:07.547 -> Liters: 0.00
21:16:07.623 -> Payload received for DPF burns: 6220F200
21:16:07.623 -> DPF burns: 0
21:16:09.697 -> Payload received for rpm: 410C0FB1
21:16:09.697 -> RPM: 1004
21:16:09.768 -> Payload received for soot: 62336A36
21:16:09.768 -> Soot: 0
21:16:09.838 -> Payload received for liters: 62132A05D2
21:16:09.838 -> Liters: 0.00
21:16:09.907 -> Payload received for DPF burns: 6220F200
21:16:09.907 -> DPF burns: 0
21:16:11.979 -> Payload received for rpm: 410C148E
21:16:11.979 -> RPM: 1315
21:16:12.054 -> Payload received for soot: 62336A36
21:16:12.054 -> Soot: 0
21:16:12.127 -> Payload received for liters: 62132A05D2
21:16:12.127 -> Liters: 0.00
21:16:12.200 -> Payload received for DPF burns: 6220F200
21:16:12.200 -> DPF burns: 0
21:16:14.284 -> Payload received for rpm: 410C14A6
21:16:14.284 -> RPM: 1321
21:16:14.359 -> Payload received for soot: 62336A36
21:16:14.359 -> Soot: 0
21:16:14.430 -> Payload received for liters: 62132A05D2
21:16:14.430 -> Liters: 0.00
21:16:14.503 -> Payload received for DPF burns: 6220F200
21:16:14.503 -> DPF burns: 0
21:16:16.534 -> Payload received for rpm: 410C13D3
21:16:16.534 -> RPM: 1268
21:16:16.606 -> Payload received for soot: 62336A36
21:16:16.606 -> Soot: 0
21:16:16.678 -> Payload received for liters: 62132A05D2
21:16:16.678 -> Liters: 0.00
21:16:16.749 -> Payload received for DPF burns: 6220F200
21:16:16.783 -> DPF burns: 0
21:16:18.830 -> Payload received for rpm: 410C175F
21:16:18.830 -> RPM: 1495
21:16:18.902 -> Payload received for soot: 62336A36
21:16:18.902 -> Soot: 0
21:16:18.975 -> Payload received for liters: 62132A05D2
21:16:18.975 -> Liters: 0.00
21:16:19.047 -> Payload received for DPF burns: 6220F200
21:16:19.047 -> DPF burns: 0
21:16:21.074 -> Payload received for rpm: 410C0FFD
21:16:21.074 -> RPM: 1023
21:16:21.144 -> Payload received for soot: 62336A36
21:16:21.144 -> Soot: 0
21:16:21.219 -> Payload received for liters: 62132A05D2
21:16:21.219 -> Liters: 0.00

(...)

21:16:39.381 -> Liters: 0.00
21:16:39.419 -> Payload received for DPF burns: 6220F200
21:16:39.419 -> DPF burns: 0
21:16:41.503 -> Payload received for rpm: 410C0F9F
21:16:41.503 -> RPM: 999
21:16:41.571 -> Payload received for soot: 62336A36
21:16:41.571 -> Soot: 0
21:16:41.645 -> Payload received for liters: 62132A05D1
21:16:41.645 -> Liters: 0.00
21:16:41.681 -> Payload received for DPF burns: 6220F200
21:16:41.681 -> DPF burns: 0
21:16:43.750 -> Payload received for rpm: 410C08E0
21:16:43.750 -> RPM: 568
21:16:43.822 -> Payload received for soot: 62336A36
21:16:43.822 -> Soot: 0
21:16:43.897 -> Payload received for liters: 62132A05D1
21:16:43.897 -> Liters: 0.00
21:16:43.969 -> Payload received for DPF burns: 6220F200
21:16:43.969 -> DPF burns: 0
21:16:46.186 -> Payload received for rpm: 410C0000
21:16:46.186 -> RPM: 0
21:16:46.186 -> Payload received for soot: 62336A36
21:16:46.186 -> Soot: 0
21:16:46.186 -> Payload received for liters: 62132A05D0
21:16:46.186 -> Liters: 0.00
21:16:46.238 -> Payload received for DPF burns: 6220F200
21:16:46.238 -> DPF burns: 0
21:16:48.294 -> Payload received for rpm: 410C0000
21:16:48.294 -> RPM: 0
21:16:48.331 -> Payload received for soot: 62336A36
21:16:48.331 -> Soot: 0
21:16:48.406 -> Payload received for liters: 62132A05D0
21:16:48.406 -> Liters: 0.00
21:16:48.476 -> Payload received for DPF burns: 6220F200 
21:16:48.476 -> DPF burns: 0
21:16:50.566 -> Payload received for rpm: 410C0000
21:16:50.566 -> RPM: 0
21:16:50.641 -> Payload received for soot: 62336A36
21:16:50.641 -> Soot: 0
21:16:50.678 -> Payload received for liters: 62132A05D0
21:16:50.711 -> Liters: 0.00
21:16:50.749 -> Payload received for DPF burns: 6220F200
21:16:50.749 -> DPF burns: 0
21:16:52.826 -> Payload received for rpm: 410C0000
21:16:52.826 -> RPM: 0
21:16:52.902 -> Payload received for soot: 62336A36
21:16:52.902 -> Soot: 0
21:16:52.975 -> Payload received for liters: 62132A05D0
21:16:52.975 -> Liters: 0.00
21:16:53.047 -> Payload received for DPF burns: 6220F200
21:16:53.047 -> DPF burns: 0
21:16:55.110 -> Payload received for rpm: 410C0000
21:16:55.110 -> RPM: 0
21:16:55.146 -> Payload received for soot: 62336A36
21:16:55.146 -> Soot: 0
21:16:55.218 -> Payload received for liters: 62132A05D0
21:16:55.218 -> Liters: 0.00
21:16:55.255 -> Payload received for DPF burns: 6220F200
21:16:55.292 -> DPF burns: 0
21:16:57.334 -> Payload received for rpm: 410C0000
21:16:57.372 -> RPM: 0
21:16:57.408 -> Payload received for soot: 62336A36
21:16:57.408 -> Soot: 0
21:16:57.484 -> Payload received for liters: 62132A05D0
21:16:57.484 -> Liters: 0.00
21:16:57.553 -> Payload received for DPF burns: 6220F200
21:16:57.553 -> DPF burns: 0
21:16:59.620 -> Payload received for rpm: 410C0000
21:16:59.620 -> RPM: 0
21:16:59.696 -> Payload received for soot: 62336A36
21:16:59.696 -> Soot: 0
21:16:59.770 -> Payload received for liters: 62132A05D0
21:16:59.770 -> Liters: 0.00
21:16:59.844 -> Payload received for DPF burns: 6220F200
21:16:59.844 -> DPF burns: 0

// engine stops

21:17:01.865 -> Payload received for rpm: 
21:17:01.865 -> 	ERROR: ELM_GENERAL_ERROR
21:17:02.433 -> Payload received for soot: 62336A36
21:17:02.470 -> Soot: 0
21:17:02.507 -> Payload received for liters: 62132A05D0
21:17:02.544 -> Liters: 0.00
21:17:02.582 -> Payload received for DPF burns: 6220F200
21:17:02.582 -> DPF burns: 0
21:17:04.625 -> Payload received for rpm: 410C0000
21:17:04.625 -> RPM: 0
21:17:04.697 -> Payload received for soot: 62336A36
21:17:04.734 -> Soot: 0
21:17:04.767 -> Payload received for liters: 62132A05D0
21:17:04.805 -> Liters: 0.00
21:17:04.874 -> Payload received for DPF burns: 6220F200
21:17:04.874 -> DPF burns: 0
21:17:06.927 -> Payload received for rpm: 410C0000
21:17:06.927 -> RPM: 0
21:17:06.964 -> Payload received for soot: 62336A36
21:17:06.964 -> Soot: 0
21:17:07.039 -> Payload received for liters: 62132A05D0
21:17:07.039 -> Liters: 0.00
21:17:07.114 -> Payload received for DPF burns: 6220F200
21:17:07.114 -> DPF burns: 0
21:17:09.184 -> Payload received for rpm: 410C0000

@PowerBroker2
Copy link
Owner

PowerBroker2 commented Mar 3, 2020

Ok, I think I FINALLY got it, lol. For "long" queries like these custom ones, I needed to add an extra '\0' char to the end of the query and header char strings. This bug prevented the Arduino from identifying the response header (even though it was present in the ELM327's response).

I verified it worked with the ELM simulator.

Current lib version: 2.0.7

@miguelos6
Copy link
Author

miguelos6 commented Mar 5, 2020

Everything seems to work now, thank you!
I just need to do extended testing as 3 of 4 drives ended up with ESP32 losing connection with my OBD after few minutes (getting -1 for extended time).
I have a few additional questions :

  • how to test using ELM simulator (ie. where to / where do you run it?)
  • is there any way of speeding up the connection to OBD ? now it takes around 15-20 seconds (is it pairing during the process or what? as there is no PIN given..)
  • similarly - is there a way to increase reliability (I got -1s from to time to time)
  • how would reconnecting look like ?
    I think if condition if -1 is returned for a long time (like 10 times in a row in main loop) then following would occur :
    ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);
    ELM_PORT.connect("V-LINK")
    myELM327.begin(ELM_PORT)
    would that work ?

@PowerBroker2
Copy link
Owner

What do you mean by "getting -1"?

Do you mean the values are consistently -1 and not properly updated or is the ELM327 class's member "status" consistently -1? These two different cases mean different things and is useful in debugging.

As for speeding up initial connection to the ELM327, there's no way to do this as far as I'm aware. The main delay seems to reside in the ESP32's bluetooth library's code, so there's not much you can do "sketch level".

I'm planning on making another small update soon that will help with the reconnect issue.

@PowerBroker2
Copy link
Owner

With release 2.0.8 you can monitor the bool myELM327.connected to see if you have lost bluetooth connection or not. If it ever becomes false, you could try calling ELM_PORT.connect("OBDII"); and myELM327.begin(ELM_PORT); again to try and reconnect.

@PowerBroker2
Copy link
Owner

Seems like things are working for you, so I'll go ahead and close this issue

@policevidin
Copy link

policevidin commented Jan 15, 2021

Hello, a want to build this project in my Opel Insignia, I have a TTGO and many ELM adaptors. The problem it in "Connection"
This is the code it is from other User is not my project.
I Have ELM327 mini (blue) v1.5, ELM327 MINI v2... , ICAR2 VGATE-V-LINK, VGATE with switch.......
This is with ELM327 mini v.1.5, the other dont work connect.

configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
Attempting to connecting...
Connected to ELM327
	ERROR: ELM_TIMEOUT
Lost connection..
reconnecting..
	ERROR: ELM_TIMEOUT
Lost connection..
#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
#include <SPI.h>
#include "opel.h"
#include "BluetoothSerial.h"
#include "ELMduino.h"
#include <WiFi.h>
#include "Free_Fonts.h"

#define ELM_PORT SerialBT
#define ESP_BLUETOOTH_NAME "ESP32"

BluetoothSerial SerialBT;
ELM327 myELM327;

TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library

void setup() {
  delay(100);
  Serial.begin(115200);
  ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);

  Serial.println("Attempting to connecting...");

  tft.init();tft.setRotation(3);
  tft.setSwapBytes(true);
  tft.pushImage(0, 0, 240, 135, opel);
  delay(1000);
  
  // change "V-LINK" to your OBD reader bluetooth name //
    if (!ELM_PORT.connect("OBDII"))
   //if (!ELM_PORT.connect("V-LINK"))
   
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 1");

      tft.fillScreen(TFT_BLACK);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setCursor(10,40);
      tft.setTextFont(4);
      tft.println("OBD error 1");     
      delay(2000);
      
    // let it not connect & retest connection at the end of the loop
    //while (1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    
      tft.fillScreen(TFT_BLACK);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setCursor(10,40);
      tft.setTextFont(4);
      tft.println("OBD error 1");    

    delay(2000);
    //while (1);
  }
  
  Serial.println("Connected to ELM327");
}


void loop() {

  int32_t rpm = -1;
  int32_t soot = -1;
  int32_t burn = -1;
  int32_t km = -1;
  int32_t litersLeft = -1;
  

// read values first, then display

// read RPM
  float tempRPM = myELM327.rpm();
  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (int32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else
      printError();

// read DPF soot level
 if (myELM327.queryPID(22, 3275))       //PID DPF Level ok on torque
//  if (myELM327.queryPID(34, 13162))       //PID DPF Level
  {
    int32_t tempSoot = myELM327.findResponse();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      soot = tempSoot;
      Serial.print("DPF soot: "); Serial.println(soot);
    }
    else
      printError();
  }

// read DPF km since last regen
  if (myELM327.queryPID(22, 3277))     //PID DPF Last Regeneration ok on torque
  {
    int32_t tempKm = myELM327.findResponse();    

    if (myELM327.status == ELM_SUCCESS)
    {
      km = tempKm;
      Serial.print("DPF km: "); Serial.println(km);
    }
    else 
      printError();
  }

// read fuel liters left 
  if (myELM327.queryPID(34, 4906))      ////PID Fuel in Tank
  {
    int32_t tempLitersLeft = myELM327.findResponse() / 64.0;    

    if (myELM327.status == ELM_SUCCESS)
    {
      litersLeft = tempLitersLeft;
      Serial.print("Liters: "); Serial.println(litersLeft);
    }
    else
      printError();
  }

// read DPF burn status 0/1
  if (myELM327.queryPID(22, 3274)) //PID DPF burn status ok on torque
  {
    int32_t tempBurn = myELM327.findResponse();

    if (myELM327.status == ELM_SUCCESS)
    {
      burn = tempBurn;
      Serial.print("DPF burns: "); Serial.println(burn);
    }
    else
      printError();
  }

// reading ends, now display it all / blink screen

    if (burn > 0 && burn <11) {
      dpfBlink(soot);
    } else {
      oneScreen(soot, km, burn, litersLeft, rpm);
      delay(1000);
      // adjust the refresh rate here, mainly visible in rpm update rate
    }

  // check if it's still connected after the loop
  if (!myELM327.connected)
  {
    Serial.println("Lost connection.."); 
      tft.fillScreen(TFT_BLACK);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setFreeFont(FF18);  
      //tft.setTextFont(4);  
      tft.setCursor(10,40);
      tft.println("Lost connection.."); 
    
    // try to reconnect
    ELM_PORT.connect("OBDII");    
    Serial.println("reconnecting..");
      tft.fillScreen(TFT_BLACK);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setFreeFont(FF18);
      tft.setCursor(10,40);
      //tft.setTextFont(4);
      tft.println("reconnecting.."); 
    delay(500);
    
    myELM327.begin(ELM_PORT);    
    // ESP.restart();
  }  
  
  
}

void dpfBlink(uint8_t dpfSoot)
{
  // Serial.println("aaah! DPF burns!");
  // display 2 blinking screens
              tft.fillScreen(TFT_BLACK);
              tft.setTextColor(TFT_WHITE, TFT_BLACK);

              tft.setCursor(40,40);          
              tft.setFreeFont(FF18);     
              tft.println("DPF burns!"); 
            
              tft.setFreeFont(FF17);
              tft.setCursor(20,70); 
              tft.println("don't turn the engine off");
              
              tft.setFreeFont(FF19); 
              tft.setCursor(40,110); 
              tft.print("Soot :");tft.print(String(dpfSoot));
              tft.drawString("%", 140, 110);

              // screen blink 
              for (int a = 0; a < 13; ++a) {
              tft.invertDisplay(true);
              delay(200);
              tft.invertDisplay(false);
              delay(200);  
              }
              // screen blink

              tft.fillScreen(TFT_BLACK);
              tft.setTextColor(TFT_WHITE, TFT_BLACK);

              tft.setCursor(30,40);
              tft.setTextSize(1);

              tft.setFreeFont(FF18); 
              tft.println("DPF soot level"); 

              tft.setFreeFont(FF24); 
              tft.drawString(String(dpfSoot), 60, 75);
              tft.drawString("%", 120, 75);
  
              // screen blink
              for (int a = 0; a < 12; ++a) {
              tft.invertDisplay(true);
              delay(200);
              tft.invertDisplay(false);
              delay(200);  
              }
              // screen blink  
              
    tft.invertDisplay(true);       
    // Serial.println("DPF blink ended");
}

void oneScreen (uint8_t dpfSoot, uint16_t dpfKm, uint8_t dpfBurn, uint8_t fuel, uint16_t rpm){

      if (dpfSoot > 130) {dpfSoot = 0;}
      if (dpfKm > 999) {dpfKm = 0;}
      if (dpfBurn > 11) {dpfBurn = 0;}
      if (fuel > 100) {fuel = 0;}
      if (rpm > 7000) {rpm = 0;}
      
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  tft.setFreeFont(NULL);

  tft.drawString("DPF soot :", 10, 5, 4);
  tft.drawString(String(dpfSoot), 130, 5, 4);
        
  tft.drawString("DPF km :", 10, 31, 4);
  tft.drawString(String(dpfKm), 130, 31, 4);
          
  tft.drawString("fuel :", 10, 57, 4);
  tft.drawString(String(fuel), 130, 57, 4);
        
  tft.drawString("rpm :", 10, 83, 4);
  tft.drawString(String(rpm), 130, 83, 4);

  tft.drawString(String(dpfBurn), 220, 125, 1);
  
}

void printError()
{
  if (myELM327.status == ELM_SUCCESS) 
    Serial.println(F("\tELM_SUCCESS"));
  else if (myELM327.status == ELM_NO_RESPONSE)
    Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
  else if (myELM327.status == ELM_BUFFER_OVERFLOW)
    Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
  else if (myELM327.status == ELM_GARBAGE)
    Serial.println(F("\tERROR: ELM_GARBAGE"));
  else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
    Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
  else if (myELM327.status == ELM_NO_DATA)
    Serial.println(F("\tERROR: ELM_NO_DATA"));
  else if (myELM327.status == ELM_STOPPED)
    Serial.println(F("\tERROR: ELM_STOPPED"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_TIMEOUT"));
  else if (myELM327.status == ELM_GENERAL_ERROR)
    Serial.println(F("\tERROR: ELM_GENERAL_ERROR")); 

  delay(500);
}

@PowerBroker2
Copy link
Owner

A wide range of issues can cause ELM327's to timeout - what sort of things have you checked already? Did you read up on other people in other issues who resolved their timeout problems? Are you using a BT or WiFi ELM327?

@PowerBroker2
Copy link
Owner

Also, are you using the latest release of the library? Note that the examples have a new printError() function and the latest release has many more built-in PID processing functions:

void printError()
{
  Serial.print("Received: ");
  for (byte i = 0; i < myELM327.recBytes; i++)
    Serial.write(myELM327.payload[i]);
  Serial.println();
  
  if (myELM327.status == ELM_SUCCESS)
    Serial.println(F("\tELM_SUCCESS"));
  else if (myELM327.status == ELM_NO_RESPONSE)
    Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
  else if (myELM327.status == ELM_BUFFER_OVERFLOW)
    Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
  else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
    Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
  else if (myELM327.status == ELM_NO_DATA)
    Serial.println(F("\tERROR: ELM_NO_DATA"));
  else if (myELM327.status == ELM_STOPPED)
    Serial.println(F("\tERROR: ELM_STOPPED"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_TIMEOUT"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));

  delay(100);
}

@policevidin
Copy link

Hello and thanks for replay. I use Bluetooth ELM adaptor, and newest version on ELMduino. I use TTGO ESP32 adaptor like on this project.
https://www.instructables.com/Opel-DPF-Indicator-Monitor/
i make you're correction but no success, given me ERROR.
Serial Monitor:
18:10:36.562 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
18:10:36.562 -> configsip: 0, SPIWP:0xee
18:10:36.562 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
18:10:36.562 -> mode:DIO, clock div:1
18:10:36.562 -> load:0x3fff0018,len:4
18:10:36.562 -> load:0x3fff001c,len:1216
18:10:36.562 -> ho 0 tail 12 room 4
18:10:36.562 -> load:0x40078000,len:9720
18:10:36.562 -> ho 0 tail 12 room 4
18:10:36.562 -> load:0x40080400,len:6352
18:10:36.562 -> entry 0x400806b8
18:10:37.483 -> Attempting to connecting...
18:10:45.039 -> Connected to ELM327
18:10:46.020 -> Received:
18:10:46.020 -> ERROR: ELM_TIMEOUT
18:10:51.058 -> Lost connection..
18:11:00.532 -> reconnecting..
18:11:03.450 -> Received:
18:11:03.450 -> ERROR: ELM_TIMEOUT
18:11:08.486 -> Lost connection..

@policevidin
Copy link

If i use V-LINK (Vgate) BT Adapter, the boart restarting after unable to connect..
Serial Monitor
18:26:52.828 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
18:26:52.828 -> configsip: 0, SPIWP:0xee
18:26:52.828 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
18:26:52.828 -> mode:DIO, clock div:1
18:26:52.828 -> load:0x3fff0018,len:4
18:26:52.828 -> load:0x3fff001c,len:1216
18:26:52.828 -> ho 0 tail 12 room 4
18:26:52.828 -> load:0x40078000,len:9720
18:26:52.828 -> ho 0 tail 12 room 4
18:26:52.828 -> load:0x40080400,len:6352
18:26:52.828 -> entry 0x400806b8
18:26:53.719 -> Attempting to connecting...
18:27:27.266 -> Couldn't connect to OBD scanner - Phase 1
18:27:35.674 -> Couldn't connect to OBD scanner - Phase 2
18:27:37.707 -> Connected to ELM327
18:27:38.704 -> Received:
18:27:38.704 -> ERROR: ELM_TIMEOUT
18:27:43.819 -> Lost connection..
18:27:44.165 ->
18:27:44.165 -> Stack smashing protect failure!
18:27:44.165 ->
18:27:44.165 -> abort() was called at PC 0x400dba34 on core 0
18:27:44.165 ->
18:27:44.165 -> Backtrace: 0x40092f2c:0x3ffcfee0 0x4009315d:0x3ffcff00 0x400dba34:0x3ffcff20 0x40106ddb:0x3ffcff40 0x400fe24a:0x3ffcff90 0x4008f69d:0x3ffcffc0
18:27:44.165 ->
18:27:44.165 -> Rebooting...
18:27:44.199 -> ets Jul 29 2019 12:21:46
18:27:44.199 ->
18:27:44.199 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
18:27:44.199 -> configsip: 0, SPIWP:0xee
18:27:44.199 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
18:27:44.199 -> mode:DIO, clock div:1
18:27:44.199 -> load:0x3fff0018,len:4
18:27:44.199 -> load:0x3fff001c,len:1216
18:27:44.199 -> ho 0 tail 12 room 4
18:27:44.199 -> load:0x40078000,len:9720
18:27:44.199 -> ho 0 tail 12 room 4
18:27:44.199 -> load:0x40080400,len:6352
18:27:44.199 -> entry 0x400806b8
18:27:45.062 -> Attempting to connecting...
18:28:18.634 -> Couldn't connect to OBD scanner - Phase 1
18:28:27.050 -> Couldn't connect to OBD scanner - Phase 2
18:28:29.082 -> Connected to ELM327
18:28:30.050 -> Received:
18:28:30.050 -> ERROR: ELM_TIMEOUT
18:28:35.179 -> Lost connection..
18:28:38.395 ->
18:28:38.395 -> Stack smashing protect failure!
18:28:38.395 ->
18:28:38.395 -> abort() was called at PC 0x400dba34 on core 0
18:28:38.395 ->
18:28:38.395 -> Backtrace: 0x40092f2c:0x3ffcfee0 0x4009315d:0x3ffcff00 0x400dba34:0x3ffcff20 0x40106ddb:0x3ffcff40 0x400fe24a:0x3ffcff90 0x4008f69d:0x3ffcffc0
18:28:38.395 ->
18:28:38.395 -> Rebooting...
18:28:38.429 -> ets Jul 29 2019 12:21:46
18:28:38.429 ->
18:28:38.429 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)

@PowerBroker2
Copy link
Owner

Interesting...It looks like the ELM327 isn't responding. Perhaps it's a config issue. Try this sketch with the BT ELM327 and manually enter the following inputs into the serial monitor:

AT Z
AT E0
AT S0
AT AL
AT TP A0

Let me know what response you get

@policevidin
Copy link

Problem with sketch

The sketch name had to be modified.
Sketch names must start with a letter or number, followed by letters,
numbers, dashes, dots and underscores. Maximum length is 63 characters.
C:\Users\Dell i7\Google Drive\SERVER\Arduino\BT_Test\BT_Test.ino: In function 'void setup()':
BT_Test:22:11: error: 'LED_BUILTIN' was not declared in this scope
pinMode(LED_BUILTIN, OUTPUT);
^
exit status 1
'LED_BUILTIN' was not declared in this scope

@policevidin
Copy link

No connection, just like other sketch

17:30:43.520 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
17:30:43.520 -> configsip: 0, SPIWP:0xee
17:30:43.520 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
17:30:43.520 -> mode:DIO, clock div:1
17:30:43.520 -> load:0x3fff0018,len:4
17:30:43.520 -> load:0x3fff001c,len:1216
17:30:43.520 -> ho 0 tail 12 room 4
17:30:43.520 -> load:0x40078000,len:9720
17:30:43.520 -> ho 0 tail 12 room 4
17:30:43.520 -> load:0x40080400,len:6352
17:30:43.520 -> entry 0x400806b8
17:30:44.263 -> Attempting to connect to ELM327...
17:31:16.241 -> Couldn't connect to OBD scanner

@PowerBroker2
Copy link
Owner

Once you delete the offending lines, what's the ELM327's response?

@policevidin
Copy link

policevidin commented Jan 16, 2021

No answer from ELM, it is not connected. Can i use your code LINK with WiFI OBD adapter. i made on test-sketch but how to "#define......" the WIFI with serial like on BT "#define ELM_PORT SerialBT"

@PowerBroker2
Copy link
Owner

Either your ELM327 uses a different baud, your car isn't on, another BT device is hogging the connection, or it's defective. Also, was your car made before 2008?

@PowerBroker2
Copy link
Owner

If you want to use the WiFi ELM327, try this sketch, however, you might want to look at this first

@policevidin
Copy link

I have 5 deferent OBD Adapters. ELM327 blue some old version ELM Blue picture ELM327 v,1.5 blue, ELM327 v2.1 blue, Vgate Icar2 orange, Vgate V-LINK, And other one model of ELM327. Only ELM327 old version connected with my sketch, but ELM Old version doesn't have a CANBUS communication for my car. The car is Opel (Vauxhall) Insignia 2011 Like on the Original project. All ELM Adapters have seam chips inside.
I have one WiFi Adapter Icar2-V-LINK. I make a code, the OBD adapter connect to the Arduino TTGO adapter but no communicated with Serialport. Here is the code of my WiFi project.

`#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
#include <SPI.h>
#include "opel.h"
#include "ELMduino.h"
#include <WiFi.h>
#include "Free_Fonts.h"

const char* ssid = "V-LINK";
const char* password = "your-password";

//IP Adress of your ELM327 Dongle
IPAddress server(192, 168, 0, 4);
WiFiClient client;
ELM327 myELM327;

TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library

void setup()
{
Serial.begin(115200);
/////////////////////////////////////
tft.init();tft.setRotation(3);
tft.setSwapBytes(true);
tft.pushImage(0, 0, 240, 135, opel);
delay(1000);

/////////////////////////////////////////
// Connecting to ELM327 WiFi
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.mode(WIFI_AP);
WiFi.begin(ssid);
// WiFi.begin(ssid, password); //Use this line if your ELM327 has a password protected WiFi

while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("Connected to Wifi");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

if (client.connect(server, 35000))
Serial.println("connected");
else
{
Serial.println("connection failed");
while(1);
}

myELM327.begin(client);
}
void loop() {

uint32_t rpm = -1;
uint32_t soot = -1;
uint32_t burn = -1;
uint32_t km = -1;
uint32_t litersLeft = -1;

// read values first, then display

// read RPM
float tempRPM = myELM327.rpm();
if (myELM327.status == ELM_SUCCESS)
{
rpm = (uint32_t)tempRPM;
Serial.print("RPM: "); Serial.println(rpm);
}
else
printError();

// read DPF soot level
if (myELM327.queryPID(22, 3275)) //PID DPF Level ok on torque
// if (myELM327.queryPID(34, 13162)) //PID DPF Level
{
uint32_t tempSoot = myELM327.findResponse();

if (myELM327.status == ELM_SUCCESS)
{
  soot = tempSoot;
  Serial.print("DPF soot: "); Serial.println(soot);
}
else
  printError();

}

// read DPF km since last regen
if (myELM327.queryPID(22, 3277)) //PID DPF Last Regeneration ok on torque
{
uint32_t tempKm = myELM327.findResponse();

if (myELM327.status == ELM_SUCCESS)
{
  km = tempKm;
  Serial.print("DPF km: "); Serial.println(km);
}
else 
  printError();

}

// read fuel liters left
if (myELM327.queryPID(34, 4906)) ////PID Fuel in Tank
{
uint32_t tempLitersLeft = myELM327.findResponse() / 64.0;

if (myELM327.status == ELM_SUCCESS)
{
  litersLeft = tempLitersLeft;
  Serial.print("Liters: "); Serial.println(litersLeft);
}
else
  printError();

}

// read DPF burn status 0/1
if (myELM327.queryPID(22, 3274)) //PID DPF burn status ok on torque
{
uint32_t tempBurn = myELM327.findResponse();

if (myELM327.status == ELM_SUCCESS)
{
  burn = tempBurn;
  Serial.print("DPF burns: "); Serial.println(burn);
}
else
  printError();

}

// reading ends, now display it all / blink screen

if (burn > 0 && burn <11) {
  dpfBlink(soot);
} else {
  oneScreen(soot, km, burn, litersLeft, rpm);
  delay(1000);
  // adjust the refresh rate here, mainly visible in rpm update rate
}

// check if it's still connected after the loop
if (!myELM327.connected)
{
Serial.println("Lost connection..");
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setFreeFont(FF18);
//tft.setTextFont(4);
tft.setCursor(10,40);
tft.println("Lost connection..");
}

}

void dpfBlink(uint8_t dpfSoot)
{
// Serial.println("aaah! DPF burns!");
// display 2 blinking screens
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);

          tft.setCursor(40,40);          
          tft.setFreeFont(FF18);     
          tft.println("DPF burns!"); 
        
          tft.setFreeFont(FF17);
          tft.setCursor(20,70); 
          tft.println("don't turn the engine off");
          
          tft.setFreeFont(FF19); 
          tft.setCursor(40,110); 
          tft.print("Soot :");tft.print(String(dpfSoot));
          tft.drawString("%", 140, 110);

          // screen blink 
          for (int a = 0; a < 13; ++a) {
          tft.invertDisplay(true);
          delay(200);
          tft.invertDisplay(false);
          delay(200);  
          }
          // screen blink

          tft.fillScreen(TFT_BLACK);
          tft.setTextColor(TFT_WHITE, TFT_BLACK);

          tft.setCursor(30,40);
          tft.setTextSize(1);

          tft.setFreeFont(FF18); 
          tft.println("DPF soot level"); 

          tft.setFreeFont(FF24); 
          tft.drawString(String(dpfSoot), 60, 75);
          tft.drawString("%", 120, 75);

          // screen blink
          for (int a = 0; a < 12; ++a) {
          tft.invertDisplay(true);
          delay(200);
          tft.invertDisplay(false);
          delay(200);  
          }
          // screen blink  
          
tft.invertDisplay(true);       
// Serial.println("DPF blink ended");

}

void oneScreen (uint8_t dpfSoot, uint16_t dpfKm, uint8_t dpfBurn, uint8_t fuel, uint16_t rpm){

  if (dpfSoot > 130) {dpfSoot = 0;}
  if (dpfKm > 999) {dpfKm = 0;}
  if (dpfBurn > 11) {dpfBurn = 0;}
  if (fuel > 100) {fuel = 0;}
  if (rpm > 7000) {rpm = 0;}

tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);

tft.setFreeFont(NULL);

tft.drawString("DPF soot :", 10, 5, 4);
tft.drawString(String(dpfSoot), 130, 5, 4);

tft.drawString("DPF km :", 10, 31, 4);
tft.drawString(String(dpfKm), 130, 31, 4);

tft.drawString("fuel :", 10, 57, 4);
tft.drawString(String(fuel), 130, 57, 4);

tft.drawString("rpm :", 10, 83, 4);
tft.drawString(String(rpm), 130, 83, 4);

tft.drawString(String(dpfBurn), 220, 125, 1);

}
void printError()
{
Serial.print("Received: ");
for (byte i = 0; i < myELM327.recBytes; i++)
Serial.write(myELM327.payload[i]);
Serial.println();

if (myELM327.status == ELM_SUCCESS)
Serial.println(F("\tELM_SUCCESS"));
else if (myELM327.status == ELM_NO_RESPONSE)
Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
else if (myELM327.status == ELM_BUFFER_OVERFLOW)
Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
else if (myELM327.status == ELM_NO_DATA)
Serial.println(F("\tERROR: ELM_NO_DATA"));
else if (myELM327.status == ELM_STOPPED)
Serial.println(F("\tERROR: ELM_STOPPED"));
else if (myELM327.status == ELM_TIMEOUT)
Serial.println(F("\tERROR: ELM_TIMEOUT"));
else if (myELM327.status == ELM_TIMEOUT)
Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));

delay(100);
}`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants