GithubHelp home page GithubHelp logo

obd9141's Introduction

OBD9141

This is a library to read data from the OBD-II port through the K-line pin using either ISO 9141-2 or ISO 14230-2 (KWP).

There are numerous projects which read data from the diagnostic port and display or record this. However, I found that most of these projects either use an ELM327 chip or the communication code is interwoven with the rest of the program. This makes it hard to extract the communication parts for use in another project.

The goal of the library is to provide a simple class which handles the communication with the port. Additionally a second class has been created which can simulate responses for testing purposes.

Usage

The code has been developed using Teensy 3, the K-line transceiver IC's used were during the development were the MC33290, SN65HVDA100 and SN65HVDA195. All three transceiver IC's worked without problems when the typical application circuit from the datasheet was used. The OBD9141 class itself has been tested on one Kia car build in 2004.

For the Teensy 3.x or LC versions it is recommended to use one of the HardwareSerial ports. For use with Arduino the AltSoftSerial library is used by default. The example reader_softserial was tested with an Arduino UNO. The KWP functionality of this library was verified to work on a Teensy 3.5. For ESP32 boards, please try the reader_esp32 example.

A minimal example of how to use the SN65HVDA195 chip mentioned is given by the following schematic: Schematic of circuit using SN65HVDA195

The EN pin can either be connected to a pin on the microcontroller or just pulled high in order to always enable the chip.

In the logic folder are some recordings made with a Saleae logic analyzer, these show the state of the K-line pin using either a Bluetooth OBD-II reader or this library, these might be useful when developing your own hardware. All timing parameters can be tweaked from the header file, by tuning these parameters, performance of up to 20 requests per second has been achieved (on the same car, 6 readings per second was the maximum with the Bluetooth dongle).

Three examples are given in the example folder. The reader and simulator examples are to be used with a hardware serial port. The reader_softserial example shows how to use it with the AltSoftSerial library. For more information on how to use the library, refer to to the header files.

Timing

Several parameters related to timing are given by the specification, some others are beyond our influence. To understand how a request works, lets consider the case the 0x0D PID is requested, this represents the vehicle's speed. Timing diagram of a request

Requesting the value of a PID consists of two phases, the first is the request phase the second the response.

In the first phase, the bytes necessary for the request are written on the Tx line, according to the specification there should be a 5 millisecond delay between each symbol. The duration of this delay is defined by INTERSYMBOL_WAIT. It is possible that the ECU still discerns the bytes correctly when this delay is lowered.

The transceiver IC puts the waveform seen on the Tx line on the K-line. However, a echo of this waveform is also provided as output of the transceiver IC and is seen on the Rx of the serial port. Because this is not part of the response we have to deal with this echo. This is done by using the readBytes method to read the same number of bytes as were sent during the request. The timeout used for this read is given by (REQUEST_ECHO_TIMEOUT_MS * sent_len + WAIT_FOR_ECHO_TIMEOUT) milliseconds, where sent_len is the number of bytes sent in the request. Because the serial port used should contain a hardware buffer, very little time is spent in this readBytes call, as all the bytes from the echo should already be available and the function returns when the requested number of bytes has been read.

After the echo has been read, the waiting game begins as we wait for the ECU to answer. According to the specification this is atleast 30 milliseconds, this duration (which is the major part of a request duration) is something that cannot be influenced. The timeout set to read the response is given by (REQUEST_ANSWER_MS_PER_BYTE * ret_len + WAIT_FOR_REQUEST_ANSWER_TIMEOUT) milliseconds, ret_len represents the number of bytes expected from the ECU. Because this number is known beforehand the readBytes method can be used. According to the specification the ECU should also pause between sending the bytes, but this is not necessarily the case.

The number of bytes to be received for each phase is known beforehand so the readBytes method can be used; it ensures that we stop reading immediately after the expected amount has been read. The main impact on the performance is given by the time the ECU takes to send a response and the INTERSYMBOL_WAIT between the bytes sent on the bus. There is no delay parameter for the minimum duration between two requests, that is up to the user.

Trouble codes

The library supports reading diagnostic trouble codes from the ECU (the ones associated to the malfunction indicator light). This was made possible with extensive testing by Produmann, under issue #9.

Contrary to reading the normal OBD PID's, when trouble codes are read from the ECU the length of the answer is not known beforehand. To accomodate this a method is implemented that handles a variable length request to the ECU. In this variable length response, each trouble code is represented by two bytes. These two bytes can then be retrieved from the buffer and converted into a human readable trouble code with letter and 4 digits (for example P0113), which can then be printed to the serial port. An example on how to read the diagnostic trouble codes is available, see readDTC. Increasing the buffer size OBD9141_BUFFER_SIZE in the header file may be necessary to accomodate the response from the ECU.

The following trouble-code related modes are supported: Reading stored trouble codes (mode 0x03), clearing trouble codes (mode 0x04) and reading pending trouble codes (mode 0x07).

ISO 14230-2 (KWP)

The ISO 14230-2 protocol uses the same physical layer as 9141-2, the support for this protocol was developed under issue #11. If initKWP() is called instead of init() the KWP protocol is used for all requests onward. The provided functionality should be the same regardless of the protocol used. A sketch that just tests the KWP functionality is available readerKWP. A KWP slow init method was added based on issue #34 and issue #41, this is like the standard 9141-2 init, but v1 and v2 are not equal.

License

MIT License, see LICENSE.md.

Copyright (c) 2015 Ivor Wanders

obd9141's People

Contributors

adamvoss avatar ankayca avatar iwanders avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

obd9141's Issues

about kline

Hi Ivor

I'm trying to comunicate k-line data sending ECT temperature to a cluster from a honda s2000 who has a k-line communication, maybe your project can help me? I know this can READ a k-line, but can send k-line messages too?

thank you

How can I know if I'm doing everything right?

Hi, I'm new to this topic and would like some clearer guidance. what I mean!
if there is any how to video or pictures how to make the connection between Teensy 3 and the MC33290, SN65HVDA100 and SN65HVDA195 and the plug of my car?
my car is fiat panda 2008.
I know I'm asking a lot but any help would be a lifesaver for me

missing Serial1 declaration

All example programs missing the OBD_SERIAL_DATA_TYPE as Serial1 declaration. Because of this the programs wont compile.
Capture

how to force simulator to perform init with reader

hello iwanders,
thank you for your great work on this library.
i am using it with MC33660 and communications seems to work fine when the init is not done. however although i'm trying for days now, i cant figure out how to perform the init.
i found the intructions in OBD9141sim.h and followed them. but the simulator is not responding to the 5baud signals from the reader. it seams the simulator doesnt even run processInterrupt()
but its checking and running the first if condition from handeInit() over and over again.
i enabled #define OBD9141SIM_SIMULATE_INIT.
but (in setup?) the usage of OBD9141sim car = OBD9141sim(Serial1, RX_PIN, TX_PIN); instead of OBD9141sim car; seems to require the modification of the class too.
thanks for your effort

why using digitalwrite(tx_pin,true)

hi,

thank's you for your project.

i contact you because in your code, you uses a lot about the kline functin by passing true or false.

If you remain, the kline function are described like that

kline(bool enabled){
digitalWrite(this->tx_pin, enabled);
}

or in the arduino specification, digitalWrite function wait about HIGH or LOW.

Can you explain me this ?

However, do you think this library are compatible with fiat implementation of the Kline protocol ( ISO14230 layout 4) i can provide you the specification about the headers.

thank's

I just discovered that I "reinvented" the wheel

Hi Ivor,

I had a GSX-R 600 2011, which uses the K-line. Almost a year ago i started writing some code to comunicate with the ECU, probably i didn't found your library because you implemented the KWP recently. Anyway I see a few differences between your init sequence and mine (especially with the init message, the sequence is almost the same)

Could i ask you were did you found the resources to write them?

I am writing also because I am sure i will take some idea from your code, i really like your management of the delay 😃

here it is my library if you would like to have a look: https://github.com/aster94/Keyword-Protocol-2000

For ESP32

#include <Arduino.h>
#include "OBD9141.h"

#define RX_PIN 16 // 16  // connect to transceiver Rx for ESP32
#define TX_PIN 17  // 17  // connect to transceiver Tx

bool init_success;

OBD9141 obd;

bool printSupportedPID(uint32_t value, uint8_t offset);

void setup()
{

  Serial.begin(115200);
  obd.begin(Serial2, RX_PIN, TX_PIN);
  delay(2000);
  Serial.println("initialization");
  Serial.println("");
  
  while (!obd.init())
  {
     return;
  }
}

void loop()
{

  if (obd.getCurrentPID(0x11, 1))
  {
    Serial.print("Result 0x11 (throttle): ");
    Serial.println(obd.readUint8());
  }

  if (obd.getCurrentPID(0x0F, 1))
  {
    Serial.print("Intake air temperature ");
    Serial.println((obd.readUint8()) / 5);
  }

  if (obd.getCurrentPID(0x0B, 1))
  {
    Serial.print("absolute pressure ");
    Serial.println(obd.readUint8());
  }

  if (obd.getCurrentPID(0x05, 1))
  {
    Serial.print("Engine coolant temperature ");
    Serial.println((obd.readUint8()) / 5);
  }

  if (obd.getCurrentPID(0x42, 1))
  {
    Serial.print("volte ");
    Serial.println(obd.readUint8());
  }
  
  Serial.println("");
}

Chipkit Max32 with KWP FAST Protocol

Hi,

I am using this library to read my vehicle which works with KWP FAST Protocol.
I am using the hardware from Macchina (https://www.macchina.cc/catalog)
The MCU that I use is a Chipkit Max 32.
I am not able to get any communication with my ECU. The debug prints the following.

"Looping
Before 25 ms / 25 ms startup.
Enable port.
init_success:0
Looping
Before 25 ms / 25 ms startup.
Enable port.
init_success:0"

KWP 2000 fast init

Currently only the slow 5 baud OBD9141-2 initialisation procedure is supported. Someone requested KWP2000 fast initialisation, from the specification I attempted to make a blind implementation. This implementation can be found in the kwp2000_fast_init branch, it is untested. The added method is init_kwp_fast.

Placing this issue here for increased visibility, if anyone can test it and report whether it works or doesn't work that'd be much appreciated. If it doesn't work: pull requests are welcome, as are logic analyzer recordings of another device performing a KWP2000 fast init and recording of this library performing the fast init on the same car.

The example for esp32 does not work.

The example for esp32 did not work for me.
I remade the example for Arduino, everything works.
I modified the example for Arduino by adding SERIAL and everything worked. What's wrong with the example for ESP32 #38 and #39 .

KWP71 Compatibility

Do you think this would work with an ECU that uses the KWP71 used on some older bmw ecus?

I think its based on the ISO9141.

Here is an image with some info about the protocol:
KW71diagram

And also the page where I found this information:
http://www.km5tz.com/BMW%20850iP11.htm

I also found this repository that also mentions the ISO9141:
https://github.com/kaihara/kwp71scan/wiki

Also is there any board that I can use directly with arduino? without the need of soldering?
Something similar to this : https://pt.aliexpress.com/item/1005004779363350.html

readerKWP not working for me

I'm using the readerKWP example which have initKWP and i'm setting init_success = true; so that in order for a request to be sent but on the logic analyzer nothing happens after the initKWP.
I also tried requestKWP and request but nothing work except the init.even if I make a request without the init it doesn't send anything.

I should mention that I'm only using a logic analyzer on the TX pin only I'm not using any tranceiver still waiting for them to come.


UPDATE: Solved the problem now it works without a problem.
can you suggest how can I receive without sending any request just keep receiving the frames.

How to tweak timing?

Hey there,
great code you have written here!
I am trying to use your library in combination with an Arduino Mega and a MC33290 to log the RPM, TPS and AFR(analog) values of my motorcycle while driving (Triumph Daytona 675).
With these information it is possible for me to correct the air values in the ECU and tune the bike for better performance!

For this usage it is imortant, that i can poll the TPS und RPM as fast as possible and both at (nearly) the same time. I already got everything working, but I hope there is some way to get it a little faster.

At the moment I need 120ms to get the RPM and the TPS values (around 60ms each). These are my timing settings from the header file:

# define OBD9141_KLINE_BAUD 10400
# define OBD9141_WAIT_FOR_ECHO 3
# define OBD9141_BUFFER_SIZE 16
# define OBD9141_INTERSYMBOL_WAIT 3
# define OBD9141_AFTER_REQUEST_DELAY 20
# define OBD9141_REQUEST_ANSWER_MS_PER_BYTE 3
# define OBD9141_WAIT_FOR_REQUEST_ANSWER_TIMEOUT 0
# define OBD9141_INIT_IDLE_BUS_BEFORE 1000
# define OBD9141_INIT_POST_INIT_DELAY 50

For testing the setup I use your reader example(slightly altered). Is there a possibility to poll these two values even faster? I need RPM & TPS as close together and often as possible.
Thank you very much in advance!

LiquidCrystal_I2C problem.

Good afternoon. I'm using ESP32 and I'm facing a problem. My code works until I include the LiquidCrystal_I2C.h library. After connecting, the ECU does not communicate.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#include "OBD9141.h"
OBD9141 obd;



#define RX_PIN 16  // connect to transceiver Rx for ESP32
#define TX_PIN 17  // connect to transceiver Tx
bool init_success;



TaskHandle_t Task1;
TaskHandle_t Task2;

// Определяем пины светодиодов
const int led1 = 2;
const int led2 = 4;

unsigned long timer;  // переменная времени
float time_inj = 0;
float rpm = 0;
float q_l_sec = 0;
float l_h = 0;
float l_100 = 0;
float speed_car = 0;

void setup() {
  // lcd.init();
  // lcd.backlight();

  // lcd.setCursor(0, 0);
  // lcd.print("Hello, world!");

  Serial.begin(115200);
  obd.begin(Serial2, RX_PIN, TX_PIN);
  delay(2000);
  Serial.println("initialization");
  timer = millis();  // запускаем отсчет времени

  //создаем задачу, которая будет выполняться на ядре 0 с максимальным приоритетом (1)
  xTaskCreatePinnedToCore(
    Task1code, /* Функция задачи. */
    "Task1",   /* Ее имя. */
    10000,     /* Размер стека функции */
    NULL,      /* Параметры */
    1,         /* Приоритет */
    &Task1,    /* Дескриптор задачи для отслеживания */
    0);        /* Указываем пин для данного ядра */
  delay(500);

  //Создаем задачу, которая будет выполняться на ядре 1 с наивысшим приоритетом (1)
  xTaskCreatePinnedToCore(
    Task2code, /* Функция задачи. */
    "Task2",   /* Имя задачи. */
    10000,     /* Размер стека */
    NULL,      /* Параметры задачи */
    1,         /* Приоритет */
    &Task2,    /* Дескриптор задачи для отслеживания */
    1);        /* Указываем пин для этой задачи */
  delay(500);

  while (!obd.init()) {
    return;
  }
}

void Task1code(void* pvParameters) {

  for (;;) {

    Serial.println("Looping");

    bool init_success = obd.init();
    Serial.print("init_success:");
    Serial.println(init_success);

    if (init_success) {
      bool res;
      while (1) {
        res = obd.getCurrentPID(0x0C, 2);
        if (res) {
          Serial.print("Result 0x0C (RPM): ");
          Serial.println(obd.readUint16() / 4);
          rpm = obd.readUint16() / 4;
        }
        res = obd.getlongPID(0x60, 0x12, 2);
        if (res) {
          Serial.print("Result (time inj #1): ");
          Serial.println((obd.readUint_long16() * 2));
          time_inj = (obd.readUint_long16() * 2);
        }

        res = obd.getCurrentPID(0x0D, 1);
        if (res) {
          Serial.print("Result 0x0D (speed): ");
          speed_car = (obd.readUint8());
          Serial.println(obd.readUint8());
        }

        if (millis() - timer > 10000)  // проверяем сколько прошло миллисекунд
        {
          res = obd.getCurrentPID(0x05, 1);
          if (res) {
            Serial.print("Result 0x05 (TEMP): ");
            speed_car = (obd.readUint8() - 40);
            Serial.println(obd.readUint8() - 40);
          }
          timer = millis();  // сбрасываем таймер
        }
      }
    }
  }
}

void Task2code(void* pvParameters) {


  for (;;) {
    q_l_sec = (rpm / 60.0) * 2.0 * (time_inj / 1000000.0) * (0.13 / 60.0);
    //полная формула
    // q_l_sec = (rpm / 60.0) * (кол-во цилиндров /  2.0) * (time_inj / 1000000.0) * ((130.0 / 1000.0) / 60.0)

    l_h = q_l_sec * 3600;  //литры в час мгновенное

    l_100 = (l_h / speed_car) * 100.0;  // потуги литры на 100 км тоже потуги


    /*Serial.print("L/h ");
    Serial.println(l_h);
    Serial.print("L/100 ");
    Serial.println(l_100);
    */
  }
}



void loop() {
}

problem 'serial_port' was not declared in this scope

Hello
impossible to operate there is always an error code
src/main.cpp: In function 'void setup()':
src/main.cpp:47:13: error: 'serial_port' was not declared in this scope
obd.begin(serial_port, RX_PIN, TX_PIN);

I really don't understand where the error comes from I am using an Arduino Uno at the moment I will switch to an esp32 later

thank you in advance for your answer which will be very valuable for me and for other people because I have already seen the problem pass on several places thank you again
I don't have the slightest sign of life from my ECU on Mini Cooper S R53
I use the adapter that I attached in the photo
I connect Lin on k-line

if anyone can help me i would be very grateful thank you in advance !!

Capture d’écran 2022-09-11 à 19 40 57

Capture d’écran 2022-09-12 à 00 08 44

TJA1020 ship

KWP Slow init with v1 != v2

Hi,
I was trying to communicate with ODB2 with my 206 1.1cc auto peugeot which should have the KWB2000 slow protocol.
I built the optoisolated hardware interface and it works properly with perfect signal ascent and descent fronts.
I started testing examples of read_softserial.ino library and modified readerKWP.ino for AltSoftSerial.
The first example with debug enabled has this log :
"
Looping
Before magic 5 baud.
Before setting port.
After setting port.
First read is: 85
read v1: 233
read v2: 143
v1: 233
v2: 143
init_success: 0
"
The problem is that the numbers V1 and V2 are different and initialization fails.

With the second example it fails without log.

I don't understand why V1 values other than V2.

Some suggestions?

ESP32 Serial1 crash...

Dear Iwanders,

I would like to use OBD9141 on an ESP32 SIM800C board, where the 16/17 pins are not available. Unfortunately the Serial1 RX_PIN 4 and TX_PIN 2 configurations crash :( What am I doing wrong?

Thanks a lot!
LJ

The code:

#define RX_PIN 4 // connect to transceiver Rx for ESP32
#define TX_PIN 2 // connect to transceiver Tx

bool init_success;
OBD9141 obd;

void setup(){
    Serial.begin(115200);
    obd.begin(Serial1, RX_PIN, TX_PIN);

Serial output:
rst:0x8 (TG1WDT_SYS_RESET),boot:0x17 (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:0x3fff0030,len:1344
load:0x40078000,len:13836
load:0x40080400,len:3608
entry 0x400805f0
ets Jul 29 2019 12:21:4

Custom request, and recv full data message

Good day! I need to send my own requests through Iso9141 at a speed of 4800 baud, is it possible with the help of your library?

Set the request header and send / receive data. my car works on its own protocol Subaru select monitor (ssm2), it is physically identical to ISO9141, but the method of obtaining data is different, instead of PID, I need to request reading from the address and parse the answer myself.

How to make it work....

Hey there.

I've been trying to connect to my VW EDC16 ECU with an arduino.

I have the 33290. It looks like this chip but labeled ZAUO instead of XAIK. I put pin 1 at the square, wasn't 100% sure.

image
I connected it like this... I also swapped TX and RX pins just in case they were backwards.
image
I keep getting init_success: 0. How can this be debugged?

If I connect with my ELM327 over COM port with putty, it works. So it's something in the Arduino or chip part of my configuration.
ATSP4 = ISO 14230-4 KWP (5 baud init, 10.4 kbaud). The documentation here mentions 14230-2, could that be the problem?
ELM327-Connects.png

None of the examples is working

Hi,
I tried to get any of the examples working, but no success at all.
I want to create a simulator on K-Line. I tried this with Arduino Uno and Mega.
I assume that with all the different libraries, I am not sure if I use the correct ones.
Do you have a zipped library with all needed files?

Regards
fly2jerry

PIDS

Hey there ive been trying to get the pid call to work with no luck. im currectly connected but when calling ny other address then the 3that are in the example i get nothing displaying. like nothing at all the whole line is blan. is there a trick im missing or do i need to some how add to the library in order to read the pid i request? if so mind hinting off how to do so please

Questions and ISO 14230-2 KWP development

First I have to tell your library makes it easy. So now the questions. I don't have one of the ICs readily available (they are order be about a week to get) but I found another circuit that is floating around out there on the web, see attached:
obdii_avr

In looking through the lib I know that it can't really be used directly to drive the circuit. But if I wanted to use this circuit instead of the chip I would have to change several functions. Any suggestions?

BTW I am using the inti_kwp_fast fork.

Thanks
Mike

ESP32 support

Hello, i'm trying to use your library on esp32.I use obd.begin(Serial2, RX_PIN, TX_PIN) and pins: rx 13 and tx :32. But Serial2 default pins are 16 and 17.Even if i use the default hardware pins the rx pin is not pull up even if i mod the cpp file to INPUT_PULLUP on rx pin.

On the other side AltsoftSerial is not compatible with esp32.The alternative option for esp32 is SoftwareSerial ,
So is it possible to add software serial option for eps32 ?
Thank you in advance!

PS. Also debug option not working on eps32 (cant compile).It will perfect if all functions of library will be working on this MCU

Unable to initialize obd.init()

Hi @iwanders Thanks for your sharing. https://github.com/iwanders/OBD9141
I am trying example code 'reader_softserial' but unable to init the obd as defined here in obd.init().
Please suggest~ Thanks.

17:54:21.677 -> init_success:0
17:54:25.191 -> Looping
17:54:31.178 -> init_success:0
17:54:34.677 -> Looping
17:54:40.687 -> init_success:0
17:54:44.166 -> Looping
17:54:50.169 -> init_success:0
17:54:53.671 -> Looping

Arduino DUE functionality?

First off, thank you very much for this excellent library. I have been using it with an Arduino MEGA without any issues. I can run your "reader" example by only changing these lines to use the Serial1 hardware port:

#define RX_PIN 19
#define TX_PIN 18

Now I am working on updating my project over to an Arduino DUE, but am having some issues.

I am using the same interface hardware with both circuits and connecting to the same Serial1 port as the MEGA so that shouldn't be an issue (both 3.3V and 5V levels should be fine). I am thinking it has something to do with Serial since I am not even getting the DEBUG to print to the terminal. I am using the Native USB port so I wonder if this has anything to do with it? Any thoughts on what to try next?

Again, thanks so much for your great work!

Mode 04 Clear Trouble Codes, CEL, MIL

I couldn't find anything in the current code that will put the ECU in Mode 04 to clear trouble codes, the CEL, and/or MIL. If this feature already exists, it needs to be documented.

Assuming it doesn't exist, it should be a simple feature to add as far as I understand it. A function called OBD9141::ClearCodes or similar would be created and it would just send the hex code for Mode 04 to the ECU.

I need to add delay in between each PID request

Hello, I'm using MC33660 chip with 540 ohm K-line pull-up and I tried your reader_time example, modified it to support soft serial as I'm using Arduino Uno with only one HW serial.

When I have three PIDs in the loop, just like in example reader_softserial which polls 0x11, 0x0C, 0x0D, I'm only getting 0x11 and then 0x0D, without the middle one 0x0C. But if I add an delay(10) in between each PID poll, I get all of them. Looks like a timing problem, my ECU isn't ready to receive another request right after sending response to the one before. I haven't hooked up logic analyser yet. 10ms delay at each PID is not a problem for me, the response time is still much faster than on ELM327 so I'm good with that, but can I add a delay somewhere to the library so I won't have to enter it manually every time?

What to do when it doesn't work immediately?

This issue comes from a comment on 9448f75 by @CallMeIce.

I'm trying to use this library with Arduino Nano(v3) and SN65HVDA100 but i didn't had any luck. When you use it with Arduino UNO , did you use the same schema that was described? or did you used something else?

I tested it with the diagram as described, without R1 and D2 as they are unnecessary in my situation, be sure to set the Enable pin of the SN65HVDA100 high to enable the chip.

If your wiring is correct and the above does not help: Check the voltages; the K-line should be approximately the battery voltage most of the time, the Rx pin follows the K-line but at logic level.

I measured voltage of K-line, and was aproximately the same with batery voltage, but if I measured it again with everything connected ,voltage drop to aprox 7V. And also if I measure the SN65HVDA LIN pin without k-line connected , voltage was about 12V. Also the voltage of Rx pin , range from 0 to 3.5 V. Do you think I might fried the chip?

The K-line that drops to 7V is quite low in my opinion, you should really use R1 and D2 in order to provide sufficient pullup to the K-line. The SN65HVDA100 datasheet recommends 1k, but some other sources use ~500 ohm.

What is the output of the example sketch? If it says init_success:0 the initialization handshake with the ECU fails. In this case, go the the OBD9141.h file and uncomment this line:

#define OBD9141_DEBUG

And check the output on the serial terminal, it should look like:

Looping
Before magic 5 baud.
Before setting port.
After setting port.
First read is: 85
read v1: 8
read v2: 8
v1: 8
v2: 8
init_success:1

If the output is different, it might provide a clue what goes wrong in the OBD9141::init() method. If the handshake fails debugging this is not straightforward, you are best of by hooking up a logic analyzer and investigating what is actually happening on the K-line and on the Tx and Rx pins.

Support for different control modules?

This library uses hardcoded address for ECU.
However VAG autos use non-standard ECU address (0x01) and have many other control modules on other addresses.

esp32 with OBD9141 not work

HI IWANDERS.
I tried from 2 days to make it works but without succes!
I use esp32 wroomer 32U and a mc33290. Witrh this setup i had other library witch work at the same pinrx 16 and tx 17. For mc33290 i used a resistor 500k between 12v and k-line. I work with ECU me7.5.

If i use reader esp32 with INIT i receive :
16:17:43.716 -> Before magic 5 baud.
16:17:45.697 -> Before setting port.
16:17:45.732 -> After setting port.
16:17:45.732 -> First read is: 252
16:17:45.797 -> Timeout on reading bytes.
16:17:45.929 -> Timeout on reading bytes.
16:17:46.027 -> Timeout on reading bytes.
16:17:46.027 ->

If i tried to use INITKWPSlow
16:29:55.011 -> initialization
16:29:55.011 ->
16:29:58.026 -> Before 25 ms / 25 ms startup.
16:29:58.091 -> Enable port.
16:29:58.418 ->
16:29:58.646 ->

Please waiting your advices.
Many thanks.

k-line speed study

here are the logs made with software that uses k-line only
it uses 17 data with an average sampling rate between 300ms and 400ms

ID,Time,SPEED,RPM,ECT,IAT,MAP,MAP(psi),MAF(Kg/h),MAF(Mg/Stk),SFT,LFT,KV,KC,KN,TP,IGN1,IGN2,IGN3,IGN4,INJ,IDC,AFR,Gear,Load
1,18:59:41.334,0,2086,89,34,512,-7.1,50,200,-14.8,-9.4,0.9,0,53,7,21.38,21.38,21.38,21.38,0,0,15.2,0,48.24
2,18:59:41.704,0,2104,89,34,508,-7.1,50,198,-13.3,-9.4,1.1,0,50,7,22.5,22.5,22.5,22.5,0,0,14.9,0,48.24
3,18:59:42.074,0,2104,89,34,511,-7.1,51,202,-12.5,-9.4,0.8,0,52,7,21,21,21,21,0,0,14.8,0,48.24
4,18:59:42.444,0,2138,89,34,503,-7.2,51,199,-7.2,-9.4,0.8,0,48,7,14.63,14.63,14.63,14.63,0,0,14.7,0,48.24
5,18:59:42.813,0,2142,88,34,465,-7.8,47,183,-9.2,-9.4,0.7,0,49,6,16.5,16.5,16.5,16.5,0,0,14.8,0,45.49
6,18:59:43.184,0,2153,88,34,454,-7.9,44,170,-10.6,-9.4,0.8,0,50,7,40.5,40.5,40.5,40.5,0,0,15.1,0,41.57
7,18:59:43.554,0,2173,88,34,518,-7,48,184,-4.9,-9.4,1,0,54,8,35.63,35.63,35.63,35.63,0,0,15.1,0,42.75
8,18:59:43.924,0,2174,88,34,540,-6.7,55,211,-5.4,-9.4,0.8,0,49,8,34.13,34.13,34.13,34.13,0,0,14.6,0,49.8
9,18:59:44.294,0,2190,88,34,533,-6.8,55,209,-6.9,-9.4,0.8,0,46,8,34.13,34.13,34.13,34.13,0,0,15,0,51.37
10,18:59:44.664,0,2206,88,34,526,-6.9,55,208,-8.8,-9.4,0.9,0,53,8,34.5,34.5,34.5,34.5,0,0,14.9,0,50.98
11,18:59:45.033,0,2230,88,34,519,-7,55,206,-14.8,-9.4,0.9,0,46,7,16.88,16.88,16.88,16.88,0,0,14.9,0,49.41
12,18:59:45.403,0,2237,88,34,471,-7.7,50,186,-16,-9.4,1,0,57,7,15.38,15.38,15.38,15.38,0,0,14.9,0,47.84
13,18:59:45.773,0,2251,88,34,455,-7.9,46,170,-15.6,-9.4,0.8,0,54,7,20.25,20.25,20.25,20.25,0,0,14.6,0,41.57
14,18:59:46.143,0,2264,88,33,452,-7.9,46,169,-14,-9.4,1.1,0,51,7,21.38,21.38,21.38,21.38,0,0,14.4,0,40
15,18:59:46.513,0,2267,88,33,449,-8,45,165,-10.2,-9.4,1,0,54,7,22.13,22.13,22.13,22.13,0,0,14.7,0,40
16,18:59:46.884,0,2268,88,33,448,-8,45,165,-11.5,-9.4,0.9,0,56,7,22.13,22.13,22.13,22.13,0,0,15.2,0,40
17,18:59:47.254,0,2279,88,33,446,-8,45,165,-17.8,-9.4,0.9,0,68,7,21.38,21.38,21.38,21.38,0,0,15.1,0,40
18,18:59:47.622,0,2276,88,33,437,-8.2,45,165,-16.6,-9.4,1,0,60,6,18.38,18.38,18.38,18.38,0,0,14.8,0,40
19,18:59:47.994,0,2263,88,33,400,-8.7,42,155,-16.8,-9.4,1,0,67,4,9.75,9.75,9.75,9.75,0,0,14.2,0,38.82
20,18:59:48.364,0,2229,88,33,356,-9.3,34,127,-14.9,-9.4,0.9,0,59,4,-16.88,-16.88,-16.88,-16.88,0,0,14.1,0,32.16

Mode 0x03: Request trouble codes.

hello, your code does not have a bug-viewing mode, that's how I implemented it
cutting from my program code:

void error03(void) {     //    Error codes view основные
 flag5=1;
   kod1="0";
   kod2="0";
   kod3="0";
         
 if (init_success){
 res = obd.getPID(0, 0x03, 6);
    for (int i=0; i<6; i++){
                rxData[i]=String(obd.readUint8(i), HEX);
               }
  if (rxData[0].toInt()<10) {   //// КОД 1
       kod1="0"+rxData[0];
      } else {kod1=rxData[0];}
       if (rxData[1].toInt()<10) {
       kod1=kod1+"0"+rxData[1];
      } else {kod1=kod1+rxData[1];}

      if (rxData[2].toInt()<10) {   //// КОД 2
       kod2="0"+rxData[2];
      } else {kod2=rxData[2];}
       if (rxData[3].toInt()<10) {
       kod2=kod2+"0"+rxData[3];
      } else {kod2=kod2+rxData[3];}

      if (rxData[4].toInt()<10) {   //// КОД 3
       kod3="0"+rxData[4];
      } else {kod3=rxData[4];}
       if (rxData[5].toInt()<10) {
       kod3=kod3+"0"+rxData[5];
      } else {kod3=kod3+rxData[5];}
               
    }
}

I had to tweak the library OBD9141.cpp a bit for this:

uint8_t OBD9141::readUint8(uint8_t index){
    return this->buffer[4 + index];

buffer[4 + index] instead buffer[5 + index]

Only I can not determine the checksum for the response
when there are no engine errors, the checksum = 5
when there are errors, the checksum from 1 to 15 is not suitable, maybe you need another method?
Can you suggest your method of displaying errors?
My method works well, but without a checksum ...
here are my debug logs:

Result 0x0C (RPM): 6
Trying to get x ret_len bytes: 8
72 107 1 65 12 11 192 204 
Result: 752
Result 0x01: 6
Trying to get x ret_len bytes: 10
72 107 1 65 1 129 7 97 64 31 
Result 0x03 : 6
Trying to get x ret_len bytes: 26
72 107 1 67 1 19 0 0 0 0 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 


hex

Result 0x0C (RPM): 6
Trying to get x ret_len bytes: 8

48 6B 1 41 C B 94 A0 
Result: 741
Result 0x01: 6
Trying to get x ret_len bytes: 10

48 6B 1 41 1 81 7 61 40 1F 
Result 0x03 : 6
Trying to get x ret_len bytes: 10

48 6B 1 43 1 13 0 0 0 0  //response contains one error p0113
1 13 0 0 0 0 





Result 0x0C (RPM): 6
Trying to get x ret_len bytes: 8

48 6B 1 41 C B D4 E0 
Result: 757
Result 0x01: 6
Trying to get x ret_len bytes: 10

48 6B 1 41 1 81 7 61 40 1F 
Result 0x03 : 6
Trying to get x ret_len bytes: 10

48 6B 1 43 1 13 0 0 0 0 
1 13 0 0 0 0 
Result del: 6
Trying to get x ret_len bytes: 10

C7 0 0 0 0 0 0 0 0 0 // response to 0x04 mode when the engine is running



Result 0x0C (RPM): 6
Trying to get x ret_len bytes: 8

48 6B 1 41 C 0 0 1 
Result: 0
Result 0x01: 6
Trying to get x ret_len bytes: 10

48 6B 1 41 1 81 7 61 40 1F 
Result 0x03 : 6
Trying to get x ret_len bytes: 10

48 6B 1 43 1 13 0 0 0 0 
1 13 0 0 0 0 Result del: 6
Trying to get x ret_len bytes: 10

C7 48 6B 1 44 F8 0 0 0 0  //response to the 0x04 mode with the engine off, when the fault reset is complete



Result 0x0C (RPM): 6
Trying to get x ret_len bytes: 8

48 6B 1 41 C 0 0 1 
Result: 0
Result 0x01: 6
Trying to get x ret_len bytes: 10

48 6B 1 41 1 0 7 61 61 BF 
Result 0x03 : 6
Trying to get x ret_len bytes: 10

48 6B 1 43 0 0 0 0 0 0  //response mode 0x03 when there are no errors
0 0 0 0 0 0 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.