- Notifications
You must be signed in to change notification settings - Fork75
A class to read an ISO 9141-2 port found in car diagnostic OBD-II ports.
License
iwanders/OBD9141
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This is a library to read data from theOBD-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.
The code has been developed usingTeensy 3, the K-line transceiver IC's used were during the development were theMC33290,SN65HVDA100 andSN65HVDA195. 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 theAltSoftSerial library is used by default. The examplereader_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 thereader_esp32
example.
A minimal example of how to use the SN65HVDA195 chip mentioned is given by the following schematic:
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 aSaleae 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. Thereader
andsimulator
examples are to be used with a hardware serial port. Thereader_softserial
example shows how to use it with theAltSoftSerial library. For more information on how to use the library, refer to to the header files.
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 the0x0D
PID is requested, this represents the vehicle's speed.
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 byINTERSYMBOL_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 thereadBytes
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 thisreadBytes
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 thereadBytes
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 thereadBytes
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 theINTERSYMBOL_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.
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 byProdumann, underissue #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 exampleP0113
), which can then be printed to the serial port. An example on how to read the diagnostic trouble codes is available, seereadDTC
. Increasing the buffer sizeOBD9141_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 (mode0x03
), clearing trouble codes (mode0x04
) and reading pending trouble codes (mode0x07
).
TheISO 14230-2 protocol uses the same physical layer as 9141-2, the support for this protocol was developed underissue #11. IfinitKWP()
is called instead ofinit()
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 availablereaderKWP
. A KWP slow init method was added based onissue #34 andissue #41, this is like the standard 9141-2 init, butv1
andv2
are not equal.
MIT License, see LICENSE.md.
Copyright (c) 2015 Ivor Wanders
About
A class to read an ISO 9141-2 port found in car diagnostic OBD-II ports.