Contributors: deshi-basara, vpav, florianbeck
Organisation: Stuttgart Media University
License: GPLv3 (http://www.gnu.org/licenses/gpl-3.0.html)
ELM library is an Arduino library which handles communication with an ELM327 or ELM327 compatible chip used for car on-board diagnosis. It supports the display of current data (OBD Mode 1) and the display and clearing of diagnostic trouble codes (DTCs). Furthermore it is capable of displaying vehicle information like the VIN and the ECU Model.
Note: This library was actually developed for the LibreXC-project.
Setting up the ELM library is fairly easy.
Note: This library uses SoftwareSerial to connect to the ELM chip. SoftwareSerial is not available on all Arduino pins! See the Arduino Reference for more information
#include <elm.h>
byte serialRX = 9; // RX pin
byte serialTX = 10; // TX pin
ELM myELM(serialRX, serialTX);
void setup() {
// initialize ELM's connection at 9600 baud
int UARTbaud = 9600;
myELM.begin(UARTbaud);
// initialize serial and wait for port to open
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}
}
PIDs range from 0 to 255 and each one represents a specific sensor value. A list of PIDs is available on Wikipedia. Values for each PID get returned in a raw and partially unreadable form. Luckily this library does the dirty job for you so you don't get your hands dirty. All values come in the correct parsed form so you can use them directly (with some limits, see "Code Size" below). The values are returned as Strings however, so you might need to convert them to int, float or whatever you need.
byte pid = 0x05;
String myValue = myELM.get_pid_data(pid);
String myDescription = myELM.get_pid_desc(pid);
String myUnit = myELM.get_pid_unit(pid);
Serial.println("The value of " + myDescription + " is " + myValue + " " + myUnit);
get_available_pids()
can be used to get the values of all supported PIDs It returns a comma-separated list.
String supportedPIDs = myELM.get_supported_pids();
Serial.println("PIDs supported: " + supportedPIDs);
Each ECU supports different PIDs. To check if a specific PID is supported, pid_available()
can be used. This function is for for informative purposes only. The lib checks for PID support on startup and allows only supported PIDs to be retrieved.
boolean rpm_supported = myELM.pid_available(0x0C);
if(rpm_supported) {
Serial.println("This ECU supports display of engine RPM");
}
This function returns the diagnostic trouble codes (DTCs) stored in the ECU. The DTCs are returned in raw form. DTC parsing will be added in a later Version.
String raw_dtcs = myELM.get_dtc();
Serial.println(raw_dtcs);
This function clears all stored DTCs in the ECU. It returns true
on successful execution and false
on errors.
boolean is_cleared = myELM.clear_dtc();
if(is_cleared) {
Serial.println("DTCs cleared.");
} else {
Serial.println("Oops, an error occured.");
}
TODO describe single functions/fields
String vin = myELM.get_vin();
String ecu = myELM.get_ecu();
String voltage = myELM.get_voltage();
String protocol = myELM.get_protocol();
Serial.println("vin: " + vin + ", ecu: " + ecu + ", voltage: " + voltage + ", protocol: " + protocol);
You can reboot the ELM chip using the reset()
function. Please note: The reset can take some time, the function will wait up to 5 seconds and check if the reboot was successful.
if(myELM.reset()) {
Serial.println("Reboot successful");
} else {
Serial.println("Error during reboot.");
};
Most of the functions return either a string or a boolean value. In all cases (except pid_available()
) the value can be checked for errors. Functions with boolean return type return the error value directly. String functions can be checked against the ERROR-Constant.
String raw = myELM.get_pid_rawdata(0x0C);
if(raw.startsWith(ELM.ERROR)){
Serial.println("Sorry, could not retrieve rpm data, the error is: " + raw);
} else {
Serial.println("Engine rpm data is: " + raw);
}
This library has various limitations.
Unfortunately the lib, especially the private function parsePID()
is pretty large in size. parsePID()
is responsible for parsing the received raw data and translating it into a human readable format. The lib currently supports ~75 different PIDs. Almost each PID requires a different formula, has a different description and the value has a different unit. This results in a total of ~30k compiled code. This is too big to fit in the memory of the smaller Arduino types (Uno, Micro, Mini, Leonardo, Yun, ...). Therefore, on these plattforms the lib only parses the most important PIDs and returns the rest unparsed. Full parsing is supported on Arduino Mega.
OBD Mode | Description | Support |
---|---|---|
Mode 1 | Current data | ✅ Supported (not all PIDs supported; code size limitations, see above) |
Mode 2 | Freeze frame data | ❌ Not supported |
Mode 3 | Display stored DTCs | ✅ Supported, but no parsing of data |
Mode 4 | Clear DTCs | ✅ Supported |
Mode 5 | Oxygen sensor monitoring test results | ❌ Not supported |
Mode 6 | other component/system monitoring | ❌ Not supported |
Mode 7 | Display pending DTCs | ❌ Not supported |
Mode 8 | Control operation of on-board component/system | ❌ Not supported |
Mode 9 | Vehicle information | ⭕ Partially (VIN and ECU name) |
Mode 10 | Display permanent DTCs | ❌ Not supported |
- Error Handling
- Only automatic protocol detection, no manual protocol setting
libELM was written by Simon Schuster, Florian Beck and Viktor Pavlovic. libELM is licensed under the GNU General Public License v3.