PowerBroker2 / ELMduino

Arduino OBD-II Bluetooth Scanner Interface Library for Car Hacking Projects
MIT License
632 stars 123 forks source link

support for non-standard PIDs #4

Closed miguelos6 closed 4 years ago

miguelos6 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

is there any easy way to dump it from Bluetooth ?

PowerBroker2 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 (A256+B)/64 // OBD Header 7E0

PowerBroker2 commented 4 years ago

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 commented 4 years ago

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

miguelos6 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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

miguelos6 commented 4 years ago

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 : https://github.com/PowerBroker2/ELMduino/issues/3

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

PowerBroker2 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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 :

PowerBroker2 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

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

policevidin commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

policevidin commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

policevidin commented 3 years ago

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 // Graphics and font library for ST7735 driver chip

include

include "opel.h"

include "ELMduino.h"

include

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); }`