The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Device::ELM327 - Methods for reading OBD data with an ELM327 module.

VERSION

Version 0.14

SYNOPSIS

This module provides a Perl interface to a device containing an Elm Electronics ELM327 OBD Interpreter and provides access to the following functions:

 Read OBD parameters and extract individual values from results.
 Read OBD Trouble Codes and expand them to their full form.
 Reset OBD Trouble Codes.
 Read ELM327 parameters.
 Write and write the ELM327 data byte.
 Calibrate ELM327 Voltage.
 Switchable diagnostic trace and replay function for debugging.

The module is written entirely in Perl and works with both Linux and Windows. Depending on which operating system it is run on it uses either the Win32::SerialPort or Device::SerialPort module (which you'll need to install first) so it should work on any platform that supports one of them.

 use Device::ELM327;

  my $obd = Device::ELM327->new();

  # Read status information...
  $obd->Show("ELM identity");
  $obd->Show("Vehicle Identification Number");
  $obd->Show("Engine RPM");
  $obd->ShowTroubleCodes();

  undef $obd;

SUBROUTINES/METHODS

new - the constructor for the module.

To open the device and have it search for an ELM module:

 my $obd = Device::ELM327->new();

If you know the port name (e.g. 'COM5', '/dev/ttyUSB7' etc) it may be quicker to pass it into the function:

 my $obd = Device::ELM327->new($port_name);

To override the default serial port settings (38400, no parity, 8 data bits, 1 stop bit, no handshaking), you can pass values with or instead of the port name:

 my $port_details = "/dev/ttyUSB0:115200:none:8:1:none";
 my $obd = Device::ELM327->new($port_details);

The port name may be left out:

 my $port_details = "115200:none:8:1:none";

It is also ok to just define the port name and/or baud rate and use default values for parity, data bits, stop bits and handshake:

 my $port_details = "/dev/ttyUSB0:115200";
 

or

 my $port_details = "115200";

If you want extra debugging information, it can be enabled by setting $debug_level to a positive number in the range 1 to 3, with more information being displayed as the number increases:

 my $obd = Device::ELM327->new($port_name, $debug_level);

A value of either undef or "" can be passed for the $port_name:

 my $obd = Device::ELM327->new("", $debug_level);

The module can replay previously captured debugging information:

 my $obd = Device_ELM327->new(undef, $debug_level, $replay_filename);

To produce a file containing replayable data simply set $debug_level to 1 or higher and pipe the output to a text file:

 perl test.pl>test_output.txt

PortOK

Returns 1 if the serial port and ELM module are working or 0 if no ELM device could be connected to.

 $obd->PortOK();

ShowReadableValues

Displays the list of values that can be read from the ELM/ECU.

 $obd->ShowReadableValues();

Show

When passed the name of an OBD value (e.g. "Engine RPM") in $value_name, it displays the address of the ECU which returned the value, the name of the value which was read or the name of one of many parameters returned followed by the value and the name of any unit associated with the value.

If an error occurred, a message will be displayed instead.

 $obd->Show($value_name);

This function calls the 'Read' function.

Read

When passed the name of an OBD value (e.g. "Engine RPM") in $value_name, it returns a reference to a structure containing a status flag and any responses:

 my $response = $obd->Read($value_name);

 if ($response->{'status'} eq "ok")
 {
  foreach my $result (@{$response->{'results'}})
  {
   print "$result->{'address'} - $result->{'name'}: $result->{'value'} $result->{'unit'}\n"
  }
 }

In the example above, $result->{'address'} contains the address of the ECU which returned the value, $result->{'name'} contains the name of the value which was read or the name of one of many parameters returned. $result->{'value'} and $result->{'unit'} contain the value and the name of any unit associated with the value.

Error conditions are indicated by a value of $response->{'status'} other than 'ok' and an expanded error message in $response->{'status_message'} (the default is 'No errors detected' when there is no error).

Error Meaning ok No errors detected Zero length response No data was returned by the ECU NO DATA A 'NO DATA' response was returned by the ELM STOPPED A 'STOPPED' response was returned by the ELM Port not ok The connection to the ELM module failed Negative response The vehicle returned a negative response Unsupported name The vehicle does not support this value Unrecognised name ELM327.pm does not recognise this value

ShowTroubleCodes

Display any trouble codes on the console:

 $obd->ShowTroubleCodes();

ClearTroubleCodes

Clear any Trouble Codes and sensor data:

 $obd->ClearTroubleCodes();

Note that clearing the sensor data will cause the vehicle to run on default values until it has recalibrated itself. This may affect performance and fuel economy.

The ISO specification also insists that any user interface which invokes this function should display an "are you sure?" message to the user before calling it.

DecodeTroubleCode

Expand a trouble code (e.g. 4216) to the full ISO code (C0216)

This function is called by 'Read'.

 $decoded_code = $obd->DecodeTroubleCode($code);

CalibrateVoltage

Changes the calibration value used by the ELM module. The value $Voltage is a string containing a fixed point value of the form: xx.xx, e.g "11.99", "12.01" etc.

 $obd->CalibrateVoltage($Voltage);

The Voltage can be read by calling:

 my $response = $obd->read("Input Voltage");
 

ResetVoltage

Resets the ELM module's Voltage calibration to the factory setting:

 $obd->ResetVoltage();

WriteStoredDataByte

Writes $byte_value to the ELM module's non-volatile storage area.

 $obd->WriteStoredDataByte($byte_value);

The value of this byte can be read using:

 $obd->Read("Stored data byte");
 

Command

Send a command to the ELM, read any response and decode it if was an ECU command. AT command responses are placed in the $self->{'response'} array. Responses to ECU commands are written to the $self->{'results'} structure. On return a status of 0 indicates no errors.

This function is called by other module functions 'Read', 'ClearTroubleCodes' etc., but can be used to send commands that aren't otherwise supported.

 $status = $obd->Command($command_string);

GetResult

Returns a value from the last set of results from the ELM/ECU

$type can be one of the following: bool (1 bit), byte (8 bit), word (16 bit), dword (32 bit) or string. $number is the zero-based index into the array of results and takes the type into account such that $number=0 returns the first byte, word or dword and $number=1, returns the second. Booleans are treated the same as bytes and require individual bits to be extracted separately. For strings, $number is the offset of the start of the string.

This function is called by 'Read'.

 $obd->GetResult($type, $number);

WriteCommand

Write a command to the serial port unless replay is in progress.

This function is called by the 'Command' function.

 $status = $obd->WriteCommand($command_string);

ReadResponse

Read the ELM's response from the serial port and put each line into the $self->{'response'} array. Turn on debugging for a dump of the response array.

This function is called by the 'Command' function.

 $status = $obd->ReadResponse();

DecodeResponse

Decode the ECU response (in the $self->{'response'} array) and write the result to the $self->{'results'} structure.

This function is called by the 'Command' function.

 $status = $obd->DecodeResponse();

GetResultsCommand06_CAN

Get the results for command 06 on a CAN system.

This function is called by 'Read' and is not intended to be called by other functions.

 $obd->GetResultsCommand06_CAN($results_reference);

OpenPort

Try to find an ELM module on a COM port. If $port_details contains the name of a port, start with that one and work upwards.

To override the default serial port settings (38400, no parity, 8 data bits, 1 stop bit, no handshaking), you can pass values in $port_details in the following format:

 port_name:baud_rate:parity:data_bits:stop_bits:handshake

e.g.

 $port_details = "/dev/ttyUSB0:115200:none:8:1:none";

The port name may be left out:

 $port_details = "115200:none:8:1:none";

It is also ok to just define the port name and/or baud rate and use default values for parity, data bits, stop bits and handshake:

 $port_details = "/dev/ttyUSB0:115200";
or
 $port_details = "115200";

On Linux you may see the error: "Can't open /dev/ttyUSB0: Permission denied". This can be avoided by running as root or by adding your user to the 'dialout' group.

This function is called by 'new'.

 $obd->OpenPort($port_details);

ConfigureDevice

Set up the ELM module to return data in the required form.

This function is called by 'new' and should not be called again.

 $obd->ConfigureDevice();

FindAvailableCommands

Query the ECU to find out which commands are supported and annotate the value entries in the 'get' structure with the 'available' flag set to 0 (not supported) or 1 (supported).

This function is called by 'new' and should not be called again.

 $obd->FindAvailableCommands();

ProcessAvailableCommands

Query the ECU to find out which commands are supported and annotate the value entries in the 'get' structure with the 'available' flag set to 0 (not supported) or 1 (supported).

This function is called by 'FindAvailableCommands' and should not be called by any other functions.

 $obd->ProcessAvailableCommands($command);

Replay

Process a file containing debugging output and replay the commands through the module.

This function is called by 'new' and should not be called by other functions.

 $obd->Replay($replay_filename);

AUTHOR

Alister Perrott, <aperrott at cpan.org>

BUGS

Please report any bugs or feature requests to bug-device-elm327 at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Device-ELM327. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

Please also include a debug trace showing the error so that I can replay your vehicle data and see exactly what you're seeing. This can be done by setting $debug_level in the constructor to 1 and piping the output to a file. e.g. perl myOBD.pl&>trace.txt

SUPPORT

You can find documentation for this module with the perldoc command.

  perldoc Device::ELM327

You can also look for information at:

ACKNOWLEDGEMENTS

Many thanks to: The authors of Win32::SerialPort and Device::SerialPort. Kedar Warriner, Thomas Kaiser and Jason McCarver for their patches and suggestions for improvements. George R Ahearn for sending sample SAE J1979 debug information. Larry Wall and all the other people who have worked on Perl. ELM Electronics for creating the ELM327 module. Everyone involved with CPAN.

LICENSE AND COPYRIGHT

Copyright 2012-15 Alister Perrott.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.