ELMduino - Library for Car Hacking

Oh cool, thanks for sharing!

Hi, have still posted an issue on github but hoping here are reading some more experts than me :slight_smile:

I’m using this adapter: https://www.amazon.de/Bluetooth-Diagnose-Interface-Vgate-Scanner/dp/B07537S9G9
Name: ELM327 Bluetooth Mini Diagnose CAN BUS Interface Auto Car PKW KFZ OBD 2 MINI Vgate Scan Tool OBD2 OBDII ELM327

Working well with Torque and I can acces it manually by sending ELM327 AT commands via Android BT serial monitor and get a propper answer.

Now, I’ve tried to use it with ESP32: connect by using the name ODBII - no success, then using the MAC and getting the following:

[I][BluetoothSerial.cpp:510] _init_bt(): device name set 
[I][BluetoothSerial.cpp:225] esp_spp_cb(): ESP_SPP_INIT_EVT
[I][BluetoothSerial.cpp:722] connect(): master : remoteAddress
[I][BluetoothSerial.cpp:290] esp_spp_cb(): ESP_SPP_DISCOVERY_COMP_EVT
[I][BluetoothSerial.cpp:292] esp_spp_cb(): ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote
[I][BluetoothSerial.cpp:314] esp_spp_cb(): ESP_SPP_CL_INIT_EVT
[I][BluetoothSerial.cpp:298] esp_spp_cb(): ESP_SPP_OPEN_EVT Connected to ELM327
ASSERT_WARN(1 8), in lc_task.c at line 5054Received:
ERROR: ELM_TIMEOUT Received:
ERROR: ELM_TIMEOUT Received:
ERROR: ELM_TIMEOUT Received:
ERROR: ELM_TIMEOUT

The log says connected to ELM327 followed by timeouts.
Have also tried to set the serial baud rate to 9600 - no success.

Here is the code:

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


BluetoothSerial SerialBT;
#define ELM_PORT   SerialBT
#define DEBUG_PORT Serial

// to remove bonded devices, set to 1 in normal to 0
#define REMOVE_BONDED_DEVICES 0


ELM327 myELM327;


uint32_t rpm = 0;
String name = "OBDII";

String MACadd = "23:32:17:05:88:45"; // discovered by serial BT monitor (Android)
// converted to hex
uint8_t address[6]  = {0x23, 0x32, 0x17, 0x05, 0x88, 0x45};


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

  // 115200 | 
  DEBUG_PORT.begin(9600);
  SerialBT.setPin("1234");
  ELM_PORT.begin("ArduHUD", true);
  
  if (!ELM_PORT.connect(address))
  {
    DEBUG_PORT.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");
}


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

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


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

Does anyone has ideas or an useful hint please?
Thanks, Frank

Hello, excellent project, I hope you can help me since I can not make it work. I have bought an elm327 wifi adapter, which works fine with torque app using the ISO14430-4 protocol, i can also send you at command with telnet from the pc, on the other hand when uploading the sketch to the nodemcu (esp8266) they connect between both, but I receive error 7 or timeout, and I don't know how to continue. Please I need your help, thank you very much in advance.
Sorry bad english i'm translating with google.

digidax:
Hi, have still posted an issue on github but hoping here are reading some more experts than me :slight_smile:

I’m using this adapter: https://www.amazon.de/Bluetooth-Diagnose-Interface-Vgate-Scanner/dp/B07537S9G9
Name: ELM327 Bluetooth Mini Diagnose CAN BUS Interface Auto Car PKW KFZ OBD 2 MINI Vgate Scan Tool OBD2 OBDII ELM327
The log says connected to ELM327 followed by timeouts.
Have also tried to set the serial baud rate to 9600 - no success.

I had not the same but a similar issue:
Using a Vgate iCar 2, which has the ELM327 Version 2.1 (as does yours), I could not connect to with an ESP32. not by name and not by mac address.
I switched over to a Vgate iCar pro 4.0, which functions flawlessly.
An “old” ELM327 version 1.5 also works OK.

cabriobob:
I had not the same but a similar issue:
Using a Vgate iCar 2, which has the ELM327 Version 2.1 (as does yours), I could not connect to with an ESP32. not by name and not by mac address.
I switched over to a Vgate iCar pro 4.0, which functions flawlessly.
An "old" ELM327 version 1.5 also works OK.

I have the elm327 v.1.5 and nodemcu but this library doesn't work for me, and doing it without it is all a complication. I was able to enter the at commands from serial, but decoding them is a lot for me. Why am I not doing elmduino, help!

Please post your code and wiring diagram

Hello power broker, thank you very much for answering me and trying to help me, tremendous work you have done with the library, I hope to be able to use it, I have an elm327 v1.5 wifi connected to an esp8266 (nodemcu v3), and this esp8266 connected by usb to the pc from where I see the serial monitor. The code is the one you have put in the example and the error it gives me is timeout. I can connect to the elm327 from the pc via telnet without problems, as well as from the cell phone with the torque app and others. in advance thank you very much, below I leave the code used.

#include <ESP8266WiFi.h>
#include "ELMduino.h"


const char* ssid = "WiFi-OBDII";
//const char* password = "your-password";


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


uint32_t rpm = 0;


void setup()
{
  Serial.begin(115200);

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

  WiFi.mode(WIFI_STA);
  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");
    ESP.reset();
  }

  myELM327.begin(client);
}


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

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


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

On the other hand, I would like to share a code that works in the configuration I have (elm327v1.5, esp8266nodemcu and pc) so I rule out that the problem is the hardware, but this code does not bring the information as I want, it returns it without format and in hex

#include <ESP8266WiFi.h>

const char* ssid = "WiFi-OBDII";
//const char* pass = "pass";

//ip ELM327
IPAddress server(192, 168, 0, 10);

boolean last_in = false;

WiFiClient client;

void setup() {
Serial.begin(9600);
delay(10);

Serial.println("");
Serial.println("");
Serial.println("Conectando a ");
Serial.println(ssid);

WiFi.mode(WIFI_STA);
WiFi.begin(ssid);
// WiFi.begin(ssid, pass);

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

Serial.println("");
Serial.println("Conectado a Wifi");
Serial.println("Direccion IP: ");
Serial.println(WiFi.localIP());

  if (client.connect(server, 35000)) {
    Serial.println("Conectado");
    //Serial.println("<ATZ");
    // Make a Request
    //client.println("ATZ");
  }
  else {
    Serial.println("Error de conexion");
    ESP.reset();
  }
}

void loop() {
  if (!client.connected()) {
    Serial.println("");
    Serial.println("CLIENTE DESCONECTADO - RESETEANDO!");
    client.stop();
    ESP.reset();
  }

// si hay bytes entrantes disponibles desde el servidor, léalos e imprímalos:

  if (client.available()) {
    if (!last_in) {
      Serial.println("");
      Serial.print(">");
      last_in = true;
    }
    char c = client.read();
    //Serial.print("");
    //Serial.print(c, HEX);
    //Serial.println("");
    Serial.print(c);
  }

// siempre que haya bytes en la cola de serie, léalos y envíelos al socket si está abierto:

  while (Serial.available() > 0) {
    if (last_in) {
      //Serial.println("");
      //Serial.print("<< Enviando request");
      //Serial.println("");
      last_in = false;
    }
    char inChar = Serial.read();
    if (client.connected()) {
      client.print(inChar);
      Serial.println("");
    }
  }
}

Hello guys and P_B.

First of all amazing library, thanks for that. Secondly i have a wire connection problem here. I can connect my elm327 via wifi and can get RPM and coolant temp. I'm cool with that. But I want to transfer data via wires. I have elm327 with cable too. It has data+/- pins on it. How can i use them with this library and how to connect them into my wemos' RX TX. Any help will be appreciated.

Best wishes.

Eymen

Thank you for your kind compliment, I'm glad people find the lib useful.

Could you post a link to where you bought the ELM327? Maybe a pic too?

If it's USB, you'll need a USB host shield or an Arduino with built-in USB host functionality.

https://urun.n11.com/tespit-ve-test-cihazlari/elm327-v15-kablolu-arac-ariza-tespit-cihazi-turkce-pic18f25k80-P394066613?gclsrc=aw.ds&&cid=601002&gclid=Cj0KCQjw8rT8BRCbARIsALWiOvSUlKS6Fw1F4C83ae7azSHMr1uCoLy_SA6Xjib53ugUnd4yjW4HLyYaAou0EALw_wcB

Sorry for foreigner link. Couldnt find any same device on globalmarkets. I want to use data+/- pin behind of it.

Can i use usb ttl to convert data for uart communication?

437dc351-daf5-4a40-b827-901410f82048.jpg

f4299bf0-daa6-406f-8b7d-d52480ec88c3.jpg

437dc351-daf5-4a40-b827-901410f82048.jpg

f4299bf0-daa6-406f-8b7d-d52480ec88c3.jpg

raymurai:
Can i use usb ttl to convert data for uart communication?

No, if it's USB, you can only use a host controller to communicate with it. You can either spend $5-$15 to get a different OBDII scanner or use a host controller shield. I'd just get a bluetooth OBDII scanner (or a UART one if you can find one)

Power_Broker:
I'd just get a bluetooth OBDII scanner (or a UART one if you can find one)

Okay, thanks for your time and information. Let me try this one.
Regards.

raymurai:
https://urun.n11.com/tespit-ve-test-cihazlari/elm327-v15-kablolu-arac-ariza-tespit-cihazi-turkce-pic18f25k80-P394066613?gclsrc=aw.ds&&cid=601002&gclid=Cj0KCQjw8rT8BRCbARIsALWiOvSUlKS6Fw1F4C83ae7azSHMr1uCoLy_SA6Xjib53ugUnd4yjW4HLyYaAou0EALw_wcB

Sorry for foreigner link. Couldnt find any same device on globalmarkets. I want to use data+/- pin behind of it.

Can i use usb ttl to convert data for uart communication?

437dc351-daf5-4a40-b827-901410f82048.jpg

f4299bf0-daa6-406f-8b7d-d52480ec88c3.jpg

i have the same adapter, remove the ch340t chip board. you will find 5 pins First pin is -ve ,2nd is tx, 3rd rx, 5th +ve.
connect all 4 to the Arduino

Thanks in advance to Power_Broker for providing this lib. I'm new to Arduino World, and I find this project interesting.
I'm planning to use a USB to OBD 2 ELM 327 interface, so no Bluetooth needed. Yet, I know I should use a USB host shield.
Do I need to define different settings for SoftwareSerial at the beggining of the sketch? Any help will be appreciate.

I don't think you need to use SoftwareSerial.h specifically, but instead use the library required to interface with the USB host. I have a severe and unrelenting hate for USB host shields (even after trying to use one of my own), so I'm not very helpful on how to use those specifically. However, I'm pretty sure there's some way to connect this library with the USB host shield library.

Maybe someone else here could provide more insight

Greetings, thanks so much for sharing this great work
Could you please help me with this
I am using the ELM327 china, with HC BT and UNO
Already paired the HC with the ELM and confirmed @38400
When using the software serial test example, I connect ok but I get ERROR ELM TIMEOUT :frowning:
I tried to change the baud rate but I don't get a connection at all then
I've been trying to connect to my ELM for a long time sadly, I'm working on a cruise control code that will require the input of the engine load, rpm, and speed.
And it's all on hold because I still didn't manage to log to that ELM :slight_smile:
Also, an example of how to use other pids, like engine load will be really nice.
Thank you

There was a recent update that should help with your issue. Make sure you're using the latest version. Can you post your code? How do you know the BT devices are paired? Can you communicate through the Serial Monitor with AT commands?

[pre][color=#202124]Hi..I'm a beginner Please help me, I try to connect my car (honda crv 2005) using ELM327 v2.1 
and it can be connected but the serial monitor shows: 

Attempting to connect to ELM327 ...
Connected to ELM327
ERROR: 5
ERROR: 5 etc

is there something wrong?this my code :
#include <SoftwareSerial.h>
#include "ELMduino.h"
SoftwareSerial BTSerial(10, 11); // RX, TX
#define ELM_PORT BTSerial

ELM327 myELM327;

uint32_t rpm = 0;

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

 Serial.begin(115200);
 ELM_PORT.begin(38400);

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

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

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

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

 if (myELM327.status == ELM_SUCCESS)
 {
 rpm = (uint32_t)tempRPM;
 Serial.print("RPM: "); Serial.println(rpm);
 }
 else
 {
 Serial.print(F("\tERROR: "));
 Serial.println(myELM327.status);
 delay(100);
 }
}
[/color]

[/pre]

thanks you very much

Error 5 means the ELM327 returned a string with error message "NO DATA" because it couldn't find the data you queried. Is your library the latest version and your car on and running during the test? Also, I can't guarantee that the lib will work for any car produced before 2008.

Added a ton of new functions to automatically process almost all standard PIDs supported. See release 2.4.0!

Here’s the new PID API:

uint32_t supportedPIDs_1_20();

uint32_t monitorStatus();
uint16_t freezeDTC();
uint16_t fuelSystemStatus();
float engineLoad();
float engineCoolantTemp();
float shortTermFuelTrimBank_1();
float longTermFuelTrimBank_1();
float shortTermFuelTrimBank_2();
float longTermFuelTrimBank_2();
float fuelPressure();
uint8_t manifoldPressure();
float rpm();
int32_t kph();
float mph();
float timingAdvance();
float intakeAirTemp();
float mafRate();
float throttle();
uint8_t commandedSecAirStatus();
uint8_t oxygenSensorsPresent_2banks();
uint8_t obdStandards();
uint8_t oxygenSensorsPresent_4banks();
bool auxInputStatus();
uint16_t runTime();


uint32_t supportedPIDs_21_40();

uint16_t distTravelWithMIL();
float fuelRailPressure();
float fuelRailGuagePressure();
float commandedEGR();
float egrError();
float commandedEvapPurge();
float fuelLevel();
uint8_t warmUpsSinceCodesCleared();
uint16_t distSinceCodesCleared();
float evapSysVapPressure();
uint8_t absBaroPressure();
float catTempB1S1();
float catTempB2S1();
float catTempB1S2();
float catTempB2S2();


uint32_t supportedPIDs_41_60();

uint32_t monitorDriveCycleStatus();
float ctrlModVoltage();
float absLoad();
float commandedAirFuelRatio();
float relativeThrottle();
float ambientAirTemp();
float absThrottlePosB();
float absThrottlePosC();
float absThrottlePosD();
float absThrottlePosE();
float absThrottlePosF();
float commandedThrottleActuator();
uint16_t timeRunWithMIL();
uint16_t timeSinceCodesCleared();
float maxMafRate();
uint8_t fuelType();
float ethonolPercent();
float absEvapSysVapPressure();
float evapSysVapPressure2();
float absFuelRailPressure();
float relativePedalPos();
float hybridBatLife();
float oilTemp();
float fuelInjectTiming();
float fuelRate();
uint8_t emissionRqmts();


uint32_t supportedPIDs_61_80();

float demandedTorque();
float torque();
uint16_t referenceTorque();
uint16_t auxSupported();