Device-ELM327
view release on metacpan or search on metacpan
lib/Device/ELM327.pm view on Meta::CPAN
else
{
print "OFF\n";
}
if ($number_of_codes > 0 || $malfunction_indicator_lamp_state > 0)
{
print "$number_of_codes trouble code";
if ($number_of_codes != 1) { print "s"; }
print ":\n";
$self->Show("Emission-related diagnostic trouble codes");
$self->Show("Emission-related diagnostic trouble codes detected during current or last completed driving cycle");
}
else
{
print "No trouble codes found.\n";
}
}
#*****************************************************************
=head2 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.
=cut
sub ClearTroubleCodes
{
my ($self) = @_;
if ($self->{'debug_level'} > 0) { print "~ClearTroubleCodes\n"; }
$self->Command("04"); # Clear Trouble Codes and sensor data
my $result = $self->GetResult("byte");
return $result; # Returns 0 if codes have been cleared or error code.
}
#*****************************************************************
=head2 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);
=cut
sub DecodeTroubleCode
{
my ($self, $code) = @_;
my @codes = ("P0","P1","P2","P3","C0","C1","C2","C3","B0","B1","B2","B3","U0","U1","U2","U3");
my $code_prefix_mask = 61440;
my $code_mask = 4095;
my $number_of_codes_mask = 127;
if ($code eq "no result" || $code == 0)
{
return "No Trouble Code";
}
my $code_prefix = ($code & $code_prefix_mask) >> 12;
$code &= $code_mask;
$code = sprintf("%03X", $code);
my $decoded_code = "$codes[$code_prefix]$code";
if ($self->{'debug_level'} > 1)
{
print "Code prefix: $code_prefix, Code: $code, Decoded: $decoded_code\n";
}
return $decoded_code;
}
#*****************************************************************
=head2 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");
=cut
sub CalibrateVoltage
{
my ($self, $Voltage) = @_;
if ($self->{'debug_level'} > 0) { print "~CalibrateVoltage: $Voltage\n"; }
$self->Command("AT CV $Voltage"); # Calibrate Voltage
return ${$self->{'response'}}[0];
}
#*****************************************************************
=head2 ResetVoltage
Resets the ELM module's Voltage calibration to the factory setting:
$obd->ResetVoltage();
=cut
sub ResetVoltage
{
my ($self) = @_;
if ($self->{'debug_level'} > 0) { print "~ResetVoltage:\n"; }
$self->Command("AT CV 0000"); # Reset Voltage to factory setting
return ${$self->{'response'}}[0];
}
#*****************************************************************
=head2 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:
lib/Device/ELM327.pm view on Meta::CPAN
$self->{'results'}->{$address}->{'response_length'} = $line_number - 1; # Do not include command byte (no sub-command byte)
}
}
if ($self->{'results'}->{$address}->{'command'} == 4) { push(@line_parts, "00"); } # Command 04 only returns a 44 SID on success. Append a 0 byte to the result.
if ($self->{'results'}->{$address}->{'command'} == $command_mask) # If there was an error, shift out the real command number.
{
$self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts));
$self->{'results'}->{$address}->{'response_code'} = $line_parts[0];
}
else
{
if ($has_sub_command[$self->{'results'}->{$address}->{'command'}])
{
$self->{'results'}->{$address}->{'sub_command'} = hex(shift @line_parts);
}
else
{
$self->{'results'}->{$address}->{'sub_command'} = 0;
}
if ($self->{'results'}->{$address}->{'command'} == 2)
{
$self->{'results'}->{$address}->{'frame'} = hex(shift @line_parts);
}
}
}
}
$self->{'bus_type'} = $self->{'results'}->{$address}->{'format'};
$results->{$address}->{$line_number} = join(" ", @line_parts);
$self->{'results'}->{$address}->{'response_reason'} = $self->{'negative_response_codes'}->{$self->{'results'}->{$address}->{'response_code'}};
$status = $self->{'results'}->{$address}->{'response_reason'};
}
}
if ($self->{'debug_level'} > 2)
{
print "Decoded results:\n";
print Dumper($results);
}
foreach my $address (sort keys %{$results})
{
$result_string = "";
foreach my $line (sort keys %{$results->{$address}})
{
$result_string .= "$results->{$address}->{$line} ";
}
@{$self->{'results'}->{$address}->{'result'}} = split(' ', $result_string);
#Now turn the hex byte strings into numbers...
foreach (@{$self->{'results'}->{$address}->{'result'}})
{
$_ = hex($_);
}
}
if ($self->{'debug_level'} > 1)
{
print "\nFully decoded results:\n";
print Dumper($self->{'results'});
}
return $status;
}
#*****************************************************************
=head2 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);
=cut
sub GetResultsCommand06_CAN
{
my ($self, $results_ref) = @_;
my $results = $$results_ref;
foreach my $address (sort keys %{$self->{'results'}})
{
my $index = 0;#1;
my $number_of_header_bytes = 2; # Allow for TID and OBDMIDID
my $number_of_result_bytes = $self->{'results'}->{$address}->{'response_length'} - $number_of_header_bytes;
do
{
if ($index != 0)
{
$index++; # Skip over OBDMIDID in subsequent records.
}
# my $obdmid_id = ${$self->{'results'}->{$address}->{'result'}}[$index];
my $sdt_id = ${$self->{'results'}->{$address}->{'result'}}[$index];
my $uas_id = ${$self->{'results'}->{$address}->{'result'}}[$index+1];
my $test_value = ${$self->{'results'}->{$address}->{'result'}}[$index+2] * 256;
$test_value += ${$self->{'results'}->{$address}->{'result'}}[$index+3];
my $min_test_limit = ${$self->{'results'}->{$address}->{'result'}}[$index+4] * 256;
$min_test_limit += ${$self->{'results'}->{$address}->{'result'}}[$index+5];
my $max_test_limit = ${$self->{'results'}->{$address}->{'result'}}[$index+6] * 256;
$max_test_limit += ${$self->{'results'}->{$address}->{'result'}}[$index+7];
my $test_name = "Unrecognised test Id ($sdt_id)";
if (exists($self->{'Standardized_Test_IDs'}->{$sdt_id}))
{
$test_name = $self->{'Standardized_Test_IDs'}->{$sdt_id}->{'name'};
}
my $unit = "unknown";
if ($uas_id >= 128)
{
( run in 1.190 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )