PowerBroker2 / ELMduino

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

ELM_TIMEOUT #123

Closed zxrxth closed 2 years ago

zxrxth commented 2 years ago

Hi, i tried this code that i got from https://forum.arduino.cc/t/elmduino-library-for-car-hacking/593482/16#msg4679253

#include "ELMduino.h"

BluetoothSerial SerialBT;
#define ELM_PORT SerialBT
#define DEBUG_PORT Serial

//String MACadd = "00:10:CC:4F:36:03"; //enter the ELM327 MAC address
uint8_t address[6] = {0x00, 0x10, 0xCC, 0x4F, 0x36, 0x03}; //enter the ELM327 MAC address after the 0x

ELM327 myELM327;

uint32_t rpm = 0;

void setup()
{
#if LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
#endif

DEBUG_PORT.begin(115200);
//SerialBT.setPin("1234");
ELM_PORT.begin("ArduHUD", true);

if (!ELM_PORT.connect(address)) //"OBDII" replaced by "address"
{
DEBUG_PORT.println("Couldn't connect to OBD scanner - Phase 1");
while (1);
}

if (!myELM327.begin(ELM_PORT,true, 2000, AUTOMATIC))
{
Serial.println("Couldn't connect to OBD scanner - Phase 2");
while (1);
}

Serial.println("Connected to ELM327");
}

void loop()
{
float tempRPM = myELM327.rpm();

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

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

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

delay(100);
}

Problem: ELM_TIMEOUT

Some description: It was successfully connected based on output on the serial monitor and green light on ELM 327. But there is no blue light on ESP32, only red light which seems that the ESP is only turned on but there's no connectivity. Correct me if I'm wrong. But I'm not sure if this is related to the ELM_TIMEOUT. I also tried your suggested solution but nothing happened. When I did the AT command, nothing comes out too. Is there any error in the code? I appreciate your time in looking into it.

PowerBroker2 commented 2 years ago

Please use markdown for code snippets

Also, the API for the library has changed a lot since that forum post. I would suggest looking at the new API and current examples

zxrxth commented 2 years ago

the new API linked me to the https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting). is it the right page?

PowerBroker2 commented 2 years ago

Oops, that's my fault - I updated my comment, but here's the link for convenience: https://github.com/PowerBroker2/ELMduino#list-of-supported-obd-pid-processing-functions

zxrxth commented 2 years ago

thank you so much, I'll try the suggested example and library. will update the outcome later

zxrxth commented 2 years ago

I've tried and it was successfully connected and the rpm value also came out! But it is not the same as the one displayed on the dashboard. If I may know, why is it?

The second question is, what is the difference between List of Supported OBD PID Processing Functions and List of standard PIDs?

Next, if I may know where can I learn to interpret the output that came out on the serial monitor?

PowerBroker2 commented 2 years ago

It should be exactly the same - how off is it?

Some of the standard PIDs listed on Wikipedia are really difficult to implement with C++ functions, so those I refuse to support in this library. I can't remember off the top of my head which PIDs those are, but it's only a handful of obscure PIDs. You can still use the library's lower level functions to manually query/parse those unsupported PIDs if needed.

Are you talking about the debug prints? You can turn those off by replacing true with false in the second argument to elmduino's begin() function.

zxrxth commented 2 years ago

When I didn't press the gas pedal, the rpm value was 4294967295 -- I assumed it is the default value. Then I began to press the gas pedal, constantly on rpm 2 (by looking at the dashboard), but the rpm value on the serial monitor changes to 5, 12, and so on. The serial monitor was scrolling too fast I might miss the correct data though.

Plus I found a formula on this website. https://www.csselectronics.com/pages/obd2-explained-simple-intro It says that "The formula for speed is e.g. simply A, meaning that the A data byte (which is in HEX) is converted to decimal to get the km/h converted value (i.e. 32 becomes 50 km/h above). For e.g. RPM (PID 0C), the formula is (256*A + B) / 4." Do I need to use this formula for the displayed rpm on the serial monitor?

Oh, okay thank you for the clarification on the PIDs listed.

Oh no, not debug prints. I just want to understand the outputs like the char, for example, what it indicates -- explanation of the outputs.

PowerBroker2 commented 2 years ago

For the RPM calculations:

https://github.com/PowerBroker2/ELMduino/blob/d2be43ce5424b9782e09ce1357bba42acda15ce6/src/ELMduino.cpp#L812-L815

This means query the RPM PID, expect only 1 line of data, expect 2 bytes (A and B), and scale (256*A + B) by 1/4. This follows the equation you linked to, so the car must be giving you bad data. If you run in debug mode using the example sketch, what does the debug printout look like?

PowerBroker2 commented 2 years ago

If you have an ESP32, use "esp32_bluetooth_serial" - debug mode is enabled by default - no need to edit the sketch

zxrxth commented 2 years ago

Here's the screenshot of debug mode. I edited the code only at the part where it connects using the name to using the address because I can't connect if I use the name. Screenshot (210)

Code:

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

BluetoothSerial SerialBT;
#define ELM_PORT   SerialBT
#define DEBUG_PORT Serial

//String MACadd = "00:10:CC:4F:36:03"; //enter the ELM327 MAC address
uint8_t address[6] = {0x00, 0x10, 0xCC, 0x4F, 0x36, 0x03}; //enter the ELM327 MAC address after the 0x

ELM327 myELM327;

uint32_t rpm = 0;

void setup()
{
#if LED_BUILTIN
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
#endif

  DEBUG_PORT.begin(115200);
  //SerialBT.setPin("1234");
  ELM_PORT.begin("ArduHUD", true);

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

  if (!myELM327.begin(ELM_PORT, true, 2000, ISO_14230_FAST_INIT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }

  Serial.println("Connected to ELM327");
}

void loop()
{
  float tempRPM = myELM327.rpm();

  if (myELM327.nb_rx_state == ELM_SUCCESS)
  {
    rpm = (uint32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
    myELM327.printError();
}
PowerBroker2 commented 2 years ago

Please attach the picture using github markdown or copy and paste the text into your reply with surrounding triple backticks. For instance:

``` Debug Text ```

zxrxth commented 2 years ago

Done, I'm really sorry for the inconvenience I've caused, quite new to github.

PowerBroker2 commented 2 years ago

For some reason your car sends too many bytes as a response to this (and possibly other) PID(s). This confuses ELMduino, resulting in ridiculous RPM data. There might be a way to patch the library, but I can't support such an effort anytime soon. You could do your own workaround by replacing

float tempRPM = myELM327.rpm();

with

myELM327.rpm();
float tempRPM = (255*myELM327.responseByte_0 + myELM327.responseByte_1)/4.0;

Note, I may have the responseByte numbers mixed up - you can easily test and fix if needed

zxrxth commented 2 years ago

I see, thank you I will try and keep you updated. If I may ask, is the formula the same for other PID(s) too?

PowerBroker2 commented 2 years ago

No, but you can use this as a guide: https://en.wikipedia.org/wiki/OBD-II_PIDs

zxrxth commented 2 years ago

okay noted thank you so much.

zxrxth commented 2 years ago

Hi, I've already tried your suggestion. When I pressed the gas pedal to 1 (on the dashboard), on the serial monitor it displayed 1000 (my car rpm is x1000). I think it was successful?

PowerBroker2 commented 2 years ago

I guess so