File Coverage

blib/lib/Device/ELM327.pm
Criterion Covered Total %
statement 15 696 2.1
branch 1 324 0.3
condition 0 111 0.0
subroutine 5 27 18.5
pod 22 22 100.0
total 43 1180 3.6


line stmt bran cond sub pod time code
1             package Device::ELM327;
2            
3 1     1   17790 use strict;
  1         2  
  1         38  
4 1     1   4 use warnings;
  1         1  
  1         26  
5 1     1   626 use Data::Dumper;
  1         7176  
  1         65  
6 1     1   607 use Time::HiRes qw(sleep);
  1         1227  
  1         4  
7            
8             my $null = "\x0";
9             my $lf = "\xa";
10             my $cr = "\xd";
11             my $max_ports_to_search = 64;
12             my @has_sub_command = (0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0);
13            
14             BEGIN
15             {
16 1 50   1   305 if ($^O eq "MSWin32")
17             {
18 0         0 require Win32::SerialPort;
19             }
20             else
21             {
22 1         748 require Device::SerialPort;
23 1         43490 Device::SerialPort->import(qw( :PARAM :STAT 0.07 ));
24             }
25             }
26            
27             =head1 NAME
28            
29             Device::ELM327 - Methods for reading OBD data with an ELM327 module.
30            
31             =head1 VERSION
32            
33             Version 0.13
34            
35             =cut
36            
37             our $VERSION = '0.13';
38            
39             #*****************************************************************
40            
41             =head1 SYNOPSIS
42            
43             This module provides a Perl interface to a device containing an Elm Electronics ELM327 OBD Interpreter and provides access to the following functions:
44            
45             Read OBD parameters and extract individual values from results.
46             Read OBD Trouble Codes and expand them to their full form.
47             Reset OBD Trouble Codes.
48             Read ELM327 parameters.
49             Write and write the ELM327 data byte.
50             Calibrate ELM327 Voltage.
51             Switchable diagnostic trace and replay function for debugging.
52            
53             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.
54            
55             use Device::ELM327;
56            
57             my $obd = Device::ELM327->new();
58            
59             # Read status information...
60             $obd->Show("ELM identity");
61             $obd->Show("Vehicle Identification Number");
62             $obd->Show("Engine RPM");
63             $obd->ShowTroubleCodes();
64            
65             undef $obd;
66            
67             =head1 SUBROUTINES/METHODS
68            
69            
70             =head2 new - the constructor for the module.
71            
72             To open the device and have it search for an ELM module:
73            
74             my $obd = Device::ELM327->new();
75            
76             If you know the port name (e.g. 'COM5', '/dev/ttyUSB7' etc) it may be
77             quicker to pass it into the function:
78            
79             my $obd = Device::ELM327->new($port_name);
80            
81             To override the default serial port settings (38400, no parity, 8 data
82             bits, 1 stop bit, no handshaking), you can pass values with or instead
83             of the port name:
84            
85             my $port_details = "/dev/ttyUSB0:115200:none:8:1:none";
86             my $obd = Device::ELM327->new($port_details);
87            
88             The port name may be left out:
89            
90             my $port_details = "115200:none:8:1:none";
91            
92             It is also ok to just define the port name and/or baud rate and use
93             default values for parity, data bits, stop bits and handshake:
94            
95             my $port_details = "/dev/ttyUSB0:115200";
96            
97             or
98            
99             my $port_details = "115200";
100            
101             If you want extra debugging information, it can be enabled by setting
102             $debug_level to a positive number in the range 1 to 3, with more
103             information being displayed as the number increases:
104            
105             my $obd = Device::ELM327->new($port_name, $debug_level);
106            
107             A value of either undef or "" can be passed for the $port_name:
108            
109             my $obd = Device::ELM327->new("", $debug_level);
110            
111             The module can replay previously captured debugging information:
112            
113             my $obd = Device_ELM327->new(undef, $debug_level, $replay_filename);
114            
115             To produce a file containing replayable data simply set $debug_level to
116             1 or higher and pipe the output to a text file:
117            
118             perl test.pl>test_output.txt
119            
120             =cut
121            
122             sub new
123             {
124 0     0 1   my ($class, $port_details, $debug_level, $replay_filename) = @_;
125 0           my $self = bless { }, $class;
126            
127 0           $self->{'version'} = $VERSION;
128            
129 0           $self->{'debug_level'} = 0;
130 0 0         if (defined($debug_level))
131             {
132 0           $self->{'debug_level'} = $debug_level;
133             }
134            
135 0           $self->{'ELM_type'} = "NONE";
136 0           $self->{'bus_type'} = "unknown";
137 0           $self->{'replay_file'} = 0;
138 0           $self->{'replay_response'} = ();
139            
140 0           $self->{'last_command'} = 0;
141 0           $self->{'last_sub_command'} = 0;
142 0           $self->{'response'} = (); # Array of strings, one per line of the response.
143 0           $self->{'response_length'} = 0; # Total number of characters in the response.
144 0           $self->{'results'} = {};
145            
146 0           $self->{'number_of_results'} = 0;
147 0           $self->{'command_addresses'} = [];
148 0           $self->{'command_results'} = [];
149            
150 0           $self->{'trouble_codes'} = [];
151            
152             # ~4.5 second delay (.0001*301*(300/2))
153 0           $self->{'rr_tries'} = 300;
154 0           $self->{'rr_retry_delay'} = .0001;
155            
156             # Status codes
157 0           $self->{'status_meanings'} = {
158             "ok" => "No errors detected",
159             "Zero length response" => "No data was returned by the ECU",
160             "NO DATA" => "A 'NO DATA' response was returned by the ELM",
161             "STOPPED" => "A 'STOPPED' response was returned by the ELM",
162             "Port not ok" => "The connection to the ELM module failed",
163             "Negative response" => "The vehicle returned a negative response",
164             "Unsupported name" => "The vehicle does not support this value",
165             "Unrecognised name" => "ELM327.pm does not recognise this value",
166             "General Reject" => "Service was rejected. ECU did not specify the reason",
167             "Service Not Supported" => "The ECU does not support the requested service",
168             "Sub Function Not Supported - Invalid Format" => "The ECU does not support the arguments of the request message or the format of the argument bytes do not match the prescribed format for the service",
169             "Busy - Repeat Request" => "The ECU is temporarily too busy to perform the requested operation",
170             "Conditions Not Correct or Request Sequence Error" => "ECU prerequisite conditions not met. Have commands been issued in the correct order?",
171             "Request Correctly Received - Response Pending" => "Correct command and parameters received, but ECU is busy. Response will follow.",
172             };
173            
174            
175             # Negative response codes (received with a 7F Negative Response Service Identifier)
176 0           $self->{'negative_response_codes'} = {
177             "0" => "ok",
178             "10" => "General Reject",
179             "11" => "Service Not Supported",
180             "12" => "Sub Function Not Supported - Invalid Format",
181             "21" => "Busy - Repeat Request",
182             "22" => "Conditions Not Correct or Request Sequence Error",
183             "78" => "Request Correctly Received - Response Pending",
184             };
185            
186            
187             # ISO Standard Test Id's for use with function 6.
188 0           $self->{'Standardized_Test_IDs'} = {
189             "0" => {name => "ISO/SAE reserved"},
190             "1" => {name => "Rich to lean sensor threshold voltage (constant)"},
191             "2" => {name => "Lean to rich sensor threshold voltage (constant)"},
192             "3" => {name => "Low sensor voltage for switch time calculation (constant)"},
193             "4" => {name => "High sensor voltage for switch time calculation (constant)"},
194             "5" => {name => "Rich to lean sensor switch time (calculated)"},
195             "6" => {name => "Lean to rich sensor switch time (calculated)"},
196             "7" => {name => "Minimum sensor voltage for test cycle (calculated)"},
197             "8" => {name => "Maximum sensor voltage for test cycle (calculated)"},
198             "9" => {name => "Time between sensor transitions (calculated)"},
199             "10" => {name => "Sensor period (calculated)"},
200             "11" => {name => "Exponential Weighted Moving Average misfire counts for last ten driving cycles"},
201             "12" => {name => "Misfire counts for last/current driving cycles"},
202             "13" => {name => "Reserved for future standardization"},
203             };
204            
205            
206             # ISO Unit and scaling identifiers
207 0           $self->{'unit_and_scaling_identifiers'} = {
208             "1" => {description => "Raw Value", modifier =>"+0", unit => ""},
209             "2" => {description => "Raw Value", modifier =>"/10", unit => ""},
210             "3" => {description => "Raw Value", modifier =>"/100", unit => ""},
211             "4" => {description => "Raw Value", modifier =>"/100", unit => ""},
212             "5" => {description => "Raw Value", modifier =>"*0.0000305", unit => ""},
213             "6" => {description => "Raw Value", modifier =>"*0.000305", unit => ""},
214             "7" => {description => "rotational frequency", modifier =>"/4", unit => "rpm"},
215             "8" => {description => "Speed", modifier =>"/100", unit => "km/h"},
216             "9" => {description => "Speed", modifier =>"+0", unit => "km/h"},
217             "10" => {description => "Voltage", modifier =>"*0.000122", unit => "V"},
218             "11" => {description => "Voltage", modifier =>"/1000", unit => "V"},
219             "12" => {description => "Voltage", modifier =>"/100", unit => "V"},
220             "13" => {description => "Current", modifier =>"*0.00390625", unit => "mA"},
221             "14" => {description => "Current", modifier =>"*0.001", unit => "mA"},
222             "15" => {description => "Current", modifier =>"*0.01", unit => "mA"},
223             "16" => {description => "Time", modifier =>"+0", unit => "ms"},
224             "17" => {description => "Time", modifier =>"/10", unit => "s"},
225             "18" => {description => "Time", modifier =>"+0", unit => "s"},
226             "19" => {description => "Resistance", modifier =>"/1000", unit => "Ohm"},
227             "20" => {description => "Resistance", modifier =>"/1000", unit => "kOhm"},
228             "21" => {description => "Resistance", modifier =>"+0", unit => "kOhm"},
229             "22" => {description => "Temperature", modifier =>"/10-40", unit => "°C"},
230             "23" => {description => "Pressure (Gauge)", modifier =>"*0.01", unit => "kPa"},
231             "24" => {description => "Pressure (Air pressure)", modifier =>"*0.0117", unit => "kPa"},
232             "25" => {description => "Pressure (Fuel pressure)", modifier =>"*0.079", unit => "kPa"},
233             "26" => {description => "Pressure (Gauge)", modifier =>"+0", unit => "kPa"},
234             "27" => {description => "Pressure (Diesel pressure)", modifier =>"*10", unit => "kPa"},
235             "28" => {description => "Angle", modifier =>"*0.01", unit => "°"},
236             "29" => {description => "Angle", modifier =>"/2", unit => "°"},
237             "30" => {description => "Equivalence ratio (lambda)", modifier =>"*0.0000305", unit => "lambda"},
238             "31" => {description => "Air/Fuel Ratio", modifier =>"*0.05", unit => "A/F ratio"},
239             "32" => {description => "Ratio", modifier =>"*0.0039062", unit => ""},
240             "33" => {description => "Frequency", modifier =>"/1000", unit => "Hz"},
241             "34" => {description => "Frequency", modifier =>"+0", unit => "Hz"},
242             "35" => {description => "Frequency", modifier =>"/1000", unit => "MHz"},
243             "36" => {description => "Counts", modifier =>"+0", unit => "counts"},
244             "37" => {description => "Distance", modifier =>"+0", unit => "km"},
245             "38" => {description => "Voltage per time", modifier =>"/1000", unit => "V/ms"},
246             "39" => {description => "Mass per time", modifier =>"/100", unit => "g/s"},
247             "40" => {description => "Mass per time", modifier =>"+0", unit => "g/s"},
248             "41" => {description => "Pressure per time", modifier =>"/1000", unit => "kPa/s"},
249             "42" => {description => "Mass per time", modifier =>"/1000", unit => "kg/h"},
250             "43" => {description => "Switches", modifier =>"+0", unit => "switches"},
251             "44" => {description => "Mass per cylinder", modifier =>"/100", unit => "g/cyl"},
252             "45" => {description => "Mass per stroke", modifier =>"/100", unit => "mg/stroke"},
253             "46" => {description => "True/False", modifier =>"+0", unit => ""},
254             "47" => {description => "Percent", modifier =>"/100", unit => "%"},
255             "48" => {description => "Percent", modifier =>"*0.001526", unit => "%"},
256             "49" => {description => "volume", modifier =>"/1000", unit => "L"},
257             "50" => {description => "length", modifier =>"*0.0007747", unit => "mm"},
258             "51" => {description => "Equivalence ratio (lambda)", modifier =>"*0.00024414", unit => "lambda"},
259             "52" => {description => "Time", modifier =>"+0", unit => "min"},
260             "53" => {description => "Time", modifier =>"/100", unit => "s"},
261             "54" => {description => "Weight", modifier =>"/100", unit => "g"},
262             "55" => {description => "Weight", modifier =>"/10", unit => "g"},
263             "56" => {description => "Weight", modifier =>"+0", unit => "g"},
264             "57" => {description => "Percent", modifier =>"/100", unit => "%"},
265            
266             "129" => {description => "Raw Value", modifier =>"+0", unit => ""},
267             "130" => {description => "Raw Value", modifier =>"/10", unit => ""},
268             "131" => {description => "Raw Value", modifier =>"/100", unit => ""},
269             "132" => {description => "Raw Value", modifier =>"/1000", unit => ""},
270             "133" => {description => "Raw Value", modifier =>"*0.0000305", unit => ""},
271             "134" => {description => "Raw Value", modifier =>"*0.000305", unit => ""},
272            
273             "138" => {description => "Voltage", modifier =>"*0.000122", unit => "V"},
274             "139" => {description => "Voltage", modifier =>"/1000", unit => "V"},
275             "140" => {description => "Voltage", modifier =>"/100", unit => "V"},
276             "141" => {description => "Current", modifier =>"*0.00390625", unit => "mA"},
277             "142" => {description => "Current", modifier =>"*0.001", unit => "mA"},
278            
279             "144" => {description => "Time", modifier =>"/1000", unit => "s"},
280            
281             "150" => {description => "Temperature", modifier =>"/10", unit => "°C"},
282            
283             "156" => {description => "Angle", modifier =>"*0.01", unit => "°"},
284             "157" => {description => "Angle", modifier =>"/2", unit => "°"},
285            
286             "168" => {description => "Mass per time", modifier =>"+0", unit => "g/s"},
287             "169" => {description => "Pressure per time", modifier =>"/4", unit => "Pa/s"},
288            
289             "175" => {description => "Percent", modifier =>"/100", unit => "%"},
290             "176" => {description => "Percent", modifier =>"*0.003052", unit => "%"},
291             "177" => {description => "Voltage per time", modifier =>"*2", unit => "V/ms"},
292            
293             "253" => {description => "Pressure (absolute)", modifier =>"*0.001", unit => "kPa"},
294             "254" => {description => "Pressure (vacuum)", modifier =>"/4", unit => "Pa"},
295            
296             };
297            
298 0           $self->{'get'} = {
299             "ELM identity" => { command => "AT I", available => 1, result => [{type => "AT", modifier =>"", unit=>""}] },
300             "Stored data byte" => { command => "AT RD", available => 1, result => [{type => "AT", modifier =>"", unit=>""}] },
301             "Input Voltage" => { command => "AT RV", available => 1, result => [{type => "AT", modifier =>'=~ s/V//', unit=>"V"}] },
302             "Ignition state" => { command => "AT IGN", available => 1, result => [{type => "AT", modifier =>"", unit=>""}] },
303            
304             "01 PIDs supported (01-20)" => { command => "01 00", available => 1,
305             result => [
306             {name => "Monitor status since DTCs cleared", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
307             # {name => "DTC that caused required freeze frame data storage", type => "bool_0", modifier => "&64", unit => ""},
308             {name => "Fuel systems status", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
309             {name => "Calculated LOAD Value!", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
310             {name => "Engine Coolant Temperature", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
311             {name => "Short Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
312             {name => "Long Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
313             {name => "Short Term Fuel Trim - Bank 2/4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
314            
315             {name => "Long Term Fuel Trim - Bank 2/4", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
316             {name => "Fuel Rail Pressure (gauge)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
317             {name => "Intake Manifold Absolute Pressure", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
318             {name => "Engine RPM", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
319             {name => "Vehicle Speed Sensor", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
320             {name => "Ignition Timing Advance for #1 Cylinder", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
321             {name => "Intake Air Temperature", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
322             {name => "Air Flow Rate from Mass Air Flow Sensor", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
323            
324             {name => "Absolute Throttle Position", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
325             {name => "Commanded Secondary Air Status", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
326             {name => "Location of oxygen sensors 13", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
327             {name => "Bank 1 - Sensor 1", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
328             {name => "Bank 1 - Sensor 2", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
329            
330             {name => "Bank 1 - Sensor 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
331             {name => "Bank 1 - Sensor 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
332             {name => "Bank 2 - Sensor 1 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
333            
334             {name => "Bank 2 - Sensor 2 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
335             {name => "Bank 2 - Sensor 3", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
336             {name => "Bank 2 - Sensor 4", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
337             {name => "Bank 3 - Sensor 2", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
338             {name => "Bank 4 - Sensor 1", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
339             {name => "Bank 4 - Sensor 2", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
340             {name => "OBD requirements to which vehicle is designed", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
341             {name => "Location of oxygen sensors 1D", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
342             {name => "Bank 2 - Sensor 1 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
343             {name => "Bank 2 - Sensor 2 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
344             {name => "Bank 3 - Sensor 1", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
345             {name => "Auxiliary Input Status", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
346             {name => "Time Since Engine Start", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
347             {name => "01 PIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
348             ] },
349            
350             "Monitor status since DTCs cleared" => { command => "01 01",
351             result => [
352             {name => "Number of DTCs stored in this ECU", type => "byte_0", modifier => "&127", unit => ""},
353             {name => "Malfunction Indicator Lamp (MIL) Status", type => "bool_0", modifier => "&128", unit => "off,on"},
354             {name => "Misfire monitoring supported", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
355             {name => "Fuel system monitoring supported", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
356             {name => "Comprehensive component monitoring supported", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
357             {name => "Misfire monitoring complete", type => "bool_1", modifier => "&16", unit => "not completed, completed"},
358             {name => "Fuel system monitoring complete", type => "bool_1", modifier => "&32", unit => "not completed, completed"},
359             {name => "Comprehensive component monitoring complete", type => "bool_1", modifier => "&64", unit => "not completed, completed"},
360             {name => "Catalyst monitoring supported", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
361             {name => "Heated catalyst monitoring supported", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
362             {name => "Evaporative system monitoring supported", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
363             {name => "Secondary air system monitoring supported", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
364             {name => "A/C system refrigerant monitoring supported", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
365             {name => "Oxygen sensor monitoring supported", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
366             {name => "Oxygen sensor heater monitoring supported", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
367             {name => "EGR system monitoring supported", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
368             {name => "Catalyst monitoring complete", type => "bool_3", modifier => "&1", unit => "not completed, completed"},
369             {name => "Heated catalyst monitoring complete", type => "bool_3", modifier => "&2", unit => "not completed, completed"},
370             {name => "Evaporative system monitoring complete", type => "bool_3", modifier => "&4", unit => "not completed, completed"},
371             {name => "Secondary air system monitoring complete", type => "bool_3", modifier => "&8", unit => "not completed, completed"},
372             {name => "A/C system refrigerant monitoring complete", type => "bool_3", modifier => "&16", unit => "not completed, completed"},
373             {name => "Oxygen sensor monitoring complete", type => "bool_3", modifier => "&32", unit => "not completed, completed"},
374             {name => "Oxygen sensor heater monitoring complete", type => "bool_3", modifier => "&64", unit => "not completed, completed"},
375             {name => "EGR system monitoring complete", type => "bool_3", modifier => "&128", unit => "not completed, completed"},
376             ] },
377             # DTC that caused required freeze frame data storage (PID 02) only exists for command 2.
378             "Fuel systems status" => { command => "01 03",
379             result => [
380             {name => "Fuel system 1 status", type => "byte_0", modifier => "&31", unit => "",
381             alternatives => [
382             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
383             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
384             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
385             {value => 8, meaning => "Open loop - due to detected system fault"},
386             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
387             ]
388             },
389             {name => "Fuel system 2 status", type => "byte_1", modifier => "&31", unit => "",
390             alternatives => [
391             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
392             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
393             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
394             {value => 8, meaning => "Open loop - due to detected system fault"},
395             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
396             ]
397             }
398             ] },
399            
400             "Calculated LOAD Value!" => { command => "01 04", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
401             "Engine Coolant Temperature" => { command => "01 05", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
402            
403             "Short Term Fuel Trim - Bank 1/3" => { command => "01 06",
404             result => [
405             {name => "Short Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
406             {name => "Short Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
407             ] },
408            
409             "Long Term Fuel Trim - Bank 1/3" => { command => "01 07",
410             result => [
411             {name => "Long Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
412             {name => "Long Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
413             ] },
414            
415             "Short Term Fuel Trim - Bank 2/4" => { command => "01 08",
416             result => [
417             {name => "Short Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
418             {name => "Short Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
419             ] },
420            
421             "Long Term Fuel Trim - Bank 2/4" => { command => "01 09",
422             result => [
423             {name => "Long Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
424             {name => "Long Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
425             ] },
426            
427            
428             "Fuel Rail Pressure (gauge)" => { command => "01 0A", result => [{type => "byte_0", modifier => "*3", unit => "kPa"}] },
429             "Intake Manifold Absolute Pressure" => { command => "01 0B", result => [{type => "byte_0", modifier => "*1", unit => "kPa"}] },
430             "Engine RPM" => { command => "01 0C", result => [{type => "word_0", modifier => "/4", unit => "RPM"}] },
431             "Vehicle Speed Sensor" => { command => "01 0D", result => [{type => "byte_0", modifier => "+0", unit => "km/h"}] },
432             "Ignition Timing Advance for #1 Cylinder" => { command => "01 0E", result => [{type => "signed_byte_0", modifier => "/2", unit => "°"}] },
433             "Intake Air Temperature" => { command => "01 0F", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
434             "Air Flow Rate from Mass Air Flow Sensor" => { command => "01 10", result => [{type => "word_0", modifier => "/100", unit => "g/s"}] },
435             "Absolute Throttle Position" => { command => "01 11", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
436             "Commanded Secondary Air Status" => { command => "01 12", result => [{type => "byte_0", modifier => "*100/255", unit => "",
437             alternatives => [
438             {value => 1, meaning => "upstream of first catalytic converter"},
439             {value => 2, meaning => "downstream of first catalytic converter inlet"},
440             {value => 4, meaning => "atmosphere / off"}
441             ] }
442             ] },
443            
444             "Location of oxygen sensors 13" => { command => "01 13",
445             result => [
446             {name => "Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
447             {name => "Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
448             {name => "Bank 1 - Sensor 3 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
449             {name => "Bank 1 - Sensor 4 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
450             {name => "Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
451             {name => "Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
452             {name => "Bank 2 - Sensor 3 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
453             {name => "Bank 2 - Sensor 4 present", type => "bool_0", modifier => "&128", unit => "not present,present"}
454             ] },
455            
456             "Bank 1 - Sensor 1" => { command => "01 14",
457             result => [
458             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
459             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
460             ] },
461            
462             "Bank 1 - Sensor 2" => { command => "01 15",
463             result => [
464             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
465             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
466             ] },
467            
468             "Bank 1 - Sensor 3" => { command => "01 16",
469             result => [
470             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
471             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
472             ] },
473            
474             "Bank 1 - Sensor 4" => { command => "01 17",
475             result => [
476             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
477             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
478             ] },
479            
480             "Bank 2 - Sensor 1 13" => { command => "01 18",
481             result => [
482             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
483             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
484             ] },
485            
486             "Bank 2 - Sensor 2 13" => { command => "01 19",
487             result => [
488             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
489             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
490             ] },
491            
492             "Bank 2 - Sensor 3" => { command => "01 1A",
493             result => [
494             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
495             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
496             ] },
497            
498             "Bank 2 - Sensor 4" => { command => "01 1B",
499             result => [
500             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
501             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
502             ] },
503            
504            
505             "Bank 2 - Sensor 1 1D" => { command => "01 16",
506             result => [
507             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
508             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
509             ] },
510            
511             "Bank 2 - Sensor 2 1D" => { command => "01 17",
512             result => [
513             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
514             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
515             ] },
516            
517             "Bank 3 - Sensor 1" => { command => "01 18",
518             result => [
519             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
520             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
521             ] },
522            
523             "Bank 3 - Sensor 2" => { command => "01 19",
524             result => [
525             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
526             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
527             ] },
528            
529             "Bank 4 - Sensor 1" => { command => "01 1A",
530             result => [
531             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
532             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
533             ] },
534            
535             "Bank 4 - Sensor 2" => { command => "01 1B",
536             result => [
537             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
538             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
539             ] },
540            
541            
542             "OBD requirements to which vehicle is designed" => { command => "01 1C", result => [{type => "byte_0", modifier => "+0", unit => "",
543             alternatives => [
544             {value => 1, meaning => "OBD II (California ARB)"},
545             {value => 2, meaning => "OBD (Federal EPA)"},
546             {value => 3, meaning => "OBD and OBD II"},
547             {value => 4, meaning => "OBD I"},
548             {value => 5, meaning => "Not OBD compliant"},
549             {value => 6, meaning => "EOBD"},
550             {value => 7, meaning => "EOBD and OBD II"},
551             {value => 8, meaning => "EOBD and OBD"},
552             {value => 9, meaning => "EOBD, OBD and OBD II"},
553             {value => 10, meaning => "JOBD"},
554             {value => 11, meaning => "JOBD and OBD II"},
555             {value => 12, meaning => "JOBD and EOBD"},
556             {value => 13, meaning => "JOBD, EOBD, and OBD II"}
557             ] }
558             ] },
559            
560             "Location of oxygen sensors 1D" => { command => "01 1D",
561             result => [
562             {name => "Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
563             {name => "Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
564             {name => "Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
565             {name => "Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
566             {name => "Bank 3 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
567             {name => "Bank 3 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
568             {name => "Bank 4 - Sensor 1 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
569             {name => "Bank 4 - Sensor 2 present", type => "bool_0", modifier => "&128", unit => "not present,present"},
570             ] },
571            
572             "Auxiliary Input Status" => { command => "01 1E", result => [{name => "Power Take Off (PTO) Status", type => "bool_0", modifier => "&1", unit => "off,on"}] },
573             "Time Since Engine Start" => { command => "01 1F", result => [{type => "word_0", modifier => "*10", unit => "s"}] },
574            
575             "01 PIDs supported (21-40)" => { command => "01 20",
576             result => [
577             {name => "Distance Travelled While MIL is Activated", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
578             {name => "Fuel Rail Pressure relative to manifold vacuum", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
579             {name => "Fuel Rail Pressure", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
580             {name => "Bank 1 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
581             {name => "Bank 1 - Sensor 2 (wide range O2S)", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
582            
583             {name => "Bank 1 - Sensor 3 (wide range O2S)", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
584             {name => "Bank 1 - Sensor 4 (wide range O2S)", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
585             {name => "Bank 2 - Sensor 1 (wide range O2S) 13", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
586             {name => "Bank 2 - Sensor 1 (wide range O2S) 1D", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
587             {name => "Bank 2 - Sensor 2 (wide range O2S) 1D", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
588             {name => "Bank 3 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
589            
590             {name => "Bank 2 - Sensor 2 (wide range O2S) 13", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
591             {name => "Bank 2 - Sensor 3 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
592             {name => "Bank 2 - Sensor 4 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
593             {name => "Bank 3 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
594             {name => "Bank 4 - Sensor 1 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
595             {name => "Bank 4 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
596            
597             {name => "Commanded EGR", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
598             {name => "EGR Error", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
599             {name => "Commanded Evaporative Purge", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
600             {name => "Fuel Level Input", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
601             {name => "Number of warm-ups since diagnostic trouble codes cleared", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
602            
603             {name => "Distance since diagnostic trouble codes cleared", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
604             {name => "Evap System Vapor Pressure", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
605             {name => "Barometric Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
606             {name => "Bank 1 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
607             {name => "Bank 1 - Sensor 2 (wide range O2S) current", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
608             {name => "Bank 1 - Sensor 3 (wide range O2S) current", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
609             {name => "Bank 1 - Sensor 4 (wide range O2S) current", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
610             {name => "Bank 2 - Sensor 1 (wide range O2S) current 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
611            
612             {name => "Bank 2 - Sensor 1 (wide range O2S) current 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
613             {name => "Bank 2 - Sensor 2 (wide range O2S) current 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
614             {name => "Bank 3 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
615            
616             {name => "Bank 2 - Sensor 2 (wide range O2S) current 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
617             {name => "Bank 2 - Sensor 3 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
618             {name => "Bank 2 - Sensor 4 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
619             {name => "Bank 3 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
620             {name => "Bank 4 - Sensor 1 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
621             {name => "Bank 4 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
622             {name => "Catalyst Temperature Bank 1, Sensor 1", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
623             {name => "Catalyst Temperature Bank 1, Sensor 2", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
624             {name => "Catalyst Temperature Bank 2, Sensor 1", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
625             {name => "Catalyst Temperature Bank 2, Sensor 2", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
626             {name => "01 PIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
627             ] },
628            
629             "Distance Travelled While MIL is Activated" => { command => "01 21", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
630             "Fuel Rail Pressure relative to manifold vacuum" => { command => "01 22", result => [{type => "word_0", modifier => "*0.079", unit => "kPa"}] },
631             "Fuel Rail Pressure" => { command => "01 23", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
632            
633             "Bank 1 - Sensor 1 (wide range O2S)" => { command => "01 24",
634             result => [
635             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
636             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
637             ] },
638            
639             "Bank 1 - Sensor 2 (wide range O2S)" => { command => "01 25",
640             result => [
641             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
642             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
643             ] },
644            
645             "Bank 1 - Sensor 3 (wide range O2S)" => { command => "01 26",
646             result => [
647             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
648             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
649             ] },
650            
651             "Bank 1 - Sensor 4 (wide range O2S)" => { command => "01 27",
652             result => [
653             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
654             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
655             ] },
656            
657             "Bank 2 - Sensor 1 (wide range O2S) 13" => { command => "01 28",
658             result => [
659             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
660             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
661             ] },
662            
663             "Bank 2 - Sensor 2 (wide range O2S) 13" => { command => "01 29",
664             result => [
665             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
666             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
667             ] },
668            
669             "Bank 2 - Sensor 3 (wide range O2S)" => { command => "01 2A",
670             result => [
671             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
672             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
673             ] },
674            
675             "Bank 2 - Sensor 4 (wide range O2S)" => { command => "01 2B",
676             result => [
677             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
678             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
679             ] },
680            
681            
682             "Bank 2 - Sensor 1 (wide range O2S) 1D" => { command => "01 26",
683             result => [
684             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
685             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
686             ] },
687            
688             "Bank 2 - Sensor 2 (wide range O2S) 1D" => { command => "01 27",
689             result => [
690             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
691             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
692             ] },
693            
694             "Bank 3 - Sensor 1 (wide range O2S)" => { command => "01 28",
695             result => [
696             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
697             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
698             ] },
699            
700             "Bank 3 - Sensor 2 (wide range O2S)" => { command => "01 29",
701             result => [
702             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
703             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
704             ] },
705            
706             "Bank 4 - Sensor 1 (wide range O2S)" => { command => "01 2A",
707             result => [
708             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
709             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
710             ] },
711            
712             "Bank 4 - Sensor 2 (wide range O2S)" => { command => "01 2B",
713             result => [
714             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
715             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
716             ] },
717            
718             "Commanded EGR" => { command => "01 2C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
719             "EGR Error" => { command => "01 2D", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
720             "Commanded Evaporative Purge" => { command => "01 2E", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
721             "Fuel Level Input" => { command => "01 2F", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
722             "Number of warm-ups since diagnostic trouble codes cleared" => { command => "01 30", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
723             "Distance since diagnostic trouble codes cleared" => { command => "01 31", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
724             "Evap System Vapor Pressure" => { command => "01 32", result => [{type => "signed_word_0", modifier => "*0.25", unit => "Pa"}] },
725             "Barometric Pressure" => { command => "01 33", result => [{type => "byte_0", modifier => "+0", unit => "kPa"}] },
726            
727             "Bank 1 - Sensor 1 (wide range O2S) current" => { command => "01 34",
728             result => [
729             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
730             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
731             ] },
732            
733             "Bank 1 - Sensor 2 (wide range O2S) current" => { command => "01 35",
734             result => [
735             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
736             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
737             ] },
738            
739             "Bank 1 - Sensor 3 (wide range O2S) current" => { command => "01 36",
740             result => [
741             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
742             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
743             ] },
744            
745             "Bank 1 - Sensor 4 (wide range O2S) current" => { command => "01 37",
746             result => [
747             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
748             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
749             ] },
750            
751             "Bank 2 - Sensor 1 (wide range O2S) current 13" => { command => "01 38",
752             result => [
753             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
754             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
755             ] },
756            
757             "Bank 2 - Sensor 2 (wide range O2S) current 13" => { command => "01 39",
758             result => [
759             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
760             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
761             ] },
762            
763             "Bank 2 - Sensor 3 (wide range O2S) current" => { command => "01 3A",
764             result => [
765             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
766             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
767             ] },
768            
769             "Bank 2 - Sensor 4 (wide range O2S) current" => { command => "01 3B",
770             result => [
771             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
772             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
773             ] },
774            
775            
776             "Bank 2 - Sensor 1 (wide range O2S) current 1D" => { command => "01 36",
777             result => [
778             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
779             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
780             ] },
781            
782             "Bank 2 - Sensor 2 (wide range O2S) current 1D" => { command => "01 37",
783             result => [
784             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
785             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
786             ] },
787            
788             "Bank 3 - Sensor 1 (wide range O2S) current" => { command => "01 38",
789             result => [
790             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
791             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
792             ] },
793            
794             "Bank 3 - Sensor 2 (wide range O2S) current" => { command => "01 39",
795             result => [
796             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
797             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
798             ] },
799            
800             "Bank 4 - Sensor 1 (wide range O2S) current" => { command => "01 3A",
801             result => [
802             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
803             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
804             ] },
805            
806             "Bank 4 - Sensor 2 (wide range O2S) current" => { command => "01 3B",
807             result => [
808             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
809             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
810             ] },
811            
812             "Catalyst Temperature Bank 1, Sensor 1" => { command => "01 3C", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
813             "Catalyst Temperature Bank 1, Sensor 2" => { command => "01 3D", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
814             "Catalyst Temperature Bank 2, Sensor 1" => { command => "01 3E", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
815             "Catalyst Temperature Bank 2, Sensor 2" => { command => "01 3F", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
816            
817             "01 PIDs supported (41-60)" => { command => "01 40",
818             result => [
819             {name => "Monitor status this driving cycle", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
820             {name => "Control Module Voltage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
821             {name => "Absolute Load Value", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
822             {name => "Commanded Equivalence Ratio", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
823             {name => "Relative Throttle Position", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
824             {name => "Ambiant Air Temperature", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
825             {name => "Absolute Throttle Position B", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
826             {name => "Absolute Throttle Position C", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
827            
828             {name => "Absolute Throttle Position D", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
829             {name => "Absolute Throttle Position E", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
830             {name => "Absolute Throttle Position F", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
831             {name => "Commanded Throttle Actuator Control", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
832             {name => "Minutes run by the engine while MIL activated", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
833             {name => "Time since diagnostic trouble codes cleared", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
834             {name => "External Test Equipment Configuration Information #1", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
835             {name => "External Test Equipment Configuration Information #2", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
836            
837             {name => "Type of fuel currently being utilized by the vehicle", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
838             {name => "Alcohol Fuel Percentage", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
839             {name => "Absolute Evap System Vapour Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
840             {name => "Evap System Vapour Pressure", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
841             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
842             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
843             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
844             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
845             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
846             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
847             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
848             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
849            
850             {name => "Fuel Rail Pressure (absolute)", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
851             {name => "Relative Accelerator Pedal Position", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
852             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
853             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
854             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
855             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
856             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
857             # {name => "01 PIDs supported (61-80)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
858             ] },
859            
860            
861             "Monitor status this driving cycle" => { command => "01 41",
862             result => [
863             {name => "Misfire monitoring Enable Status", type => "bool_1", modifier => "&1", unit => "not enabled,enabled"},
864             {name => "Fuel system monitoring Enable Status", type => "bool_1", modifier => "&2", unit => "not enabled,enabled"},
865             {name => "Comprehensive component monitoring Enable Status", type => "bool_1", modifier => "&4", unit => "not enabled,enabled"},
866             {name => "Misfire monitoring Completion Status", type => "bool_1", modifier => "&16", unit => "not completed,completed"},
867             {name => "Fuel system monitoring Completion Status", type => "bool_1", modifier => "&32", unit => "not completed,completed"},
868             {name => "Comprehensive component monitoring Completion Status", type => "bool_1", modifier => "&64", unit => "not completed,completed"},
869             {name => "Catalyst monitoring Enable Status", type => "bool_2", modifier => "&1", unit => "not enabled,enabled"},
870             {name => "Heated catalyst monitoring Enable Status", type => "bool_2", modifier => "&2", unit => "not enabled,enabled"},
871             {name => "Evaporative system monitoring Enable Status", type => "bool_2", modifier => "&4", unit => "not enabled,enabled"},
872             {name => "Secondary air system monitoring Enable Status", type => "bool_2", modifier => "&8", unit => "not enabled,enabled"},
873             {name => "A/C system refrigerant monitoring Enable Status", type => "bool_2", modifier => "&16", unit => "not enabled,enabled"},
874             {name => "Oxygen sensor monitoring Enable Status", type => "bool_2", modifier => "&32", unit => "not enabled,enabled"},
875             {name => "Oxygen sensor heater monitoring Enable Status", type => "bool_2", modifier => "&64", unit => "not enabled,enabled"},
876             {name => "EGR monitoring Enable Status", type => "bool_2", modifier => "&128", unit => "not enabled,enabled"},
877             {name => "Catalyst monitoring Completion Status", type => "bool_3", modifier => "&1", unit => "not completed,completed"},
878             {name => "Heated catalyst monitoring Completion Status", type => "bool_3", modifier => "&2", unit => "not completed,completed"},
879             {name => "Evaporative system monitoring Completion Status", type => "bool_3", modifier => "&4", unit => "not completed,completed"},
880             {name => "Secondary air system monitoring Completion Status", type => "bool_3", modifier => "&8", unit => "not completed,completed"},
881             {name => "A/C system refrigerant monitoring Completion Status", type => "bool_3", modifier => "&16", unit => "not completed,completed"},
882             {name => "Oxygen sensor monitoring Completion Status", type => "bool_3", modifier => "&32", unit => "not completed,completed"},
883             {name => "Oxygen sensor heater monitoring Completion Status", type => "bool_3", modifier => "&64", unit => "not completed,completed"},
884             {name => "EGR monitoring Completion Status", type => "bool_3", modifier => "&128", unit => "not completed,completed"}
885             ] },
886            
887             "Control Module Voltage" => { command => "01 42", result => [{type => "word_0", modifier => "*0.001", unit => "V"}] },
888             "Absolute Load Value" => { command => "01 43", result => [{type => "word_0", modifier => "*100/255", unit => "%"}] },
889             "Commanded Equivalence Ratio" => { command => "01 44", result => [{type => "word_0", modifier => "*0.0000305", unit => ""}] },
890             "Relative Throttle Position" => { command => "01 45", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
891             "Ambiant Air Temperature" => { command => "01 46", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
892             "Absolute Throttle Position B" => { command => "01 47", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
893             "Absolute Throttle Position C" => { command => "01 48", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
894             "Accelerator Pedal Position D" => { command => "01 49", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
895             "Accelerator Pedal Position E" => { command => "01 4A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
896             "Accelerator Pedal Position F" => { command => "01 4B", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
897             "Commanded Throttle Actuator Control" => { command => "01 4C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
898             "Minutes run by the engine while MIL activated" => { command => "01 4D", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
899             "Time since diagnostic trouble codes cleared" => { command => "01 4E", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
900             "External Test Equipment Configuration Information #1" => { command => "01 4F",
901             result => [
902             {name => "Maximum value for Equivalence Ratio", type => "byte_0", modifier => "+0", unit => ""},
903             {name => "Maximum value for Oxygen Sensor Voltage", type => "byte_1", modifier => "+0", unit => "V"},
904             {name => "Maximum value for Oxygen Sensor Current", type => "byte_2", modifier => "+0", unit => "mA"},
905             {name => "Maximum value for Intake Manifold Absolute Pressure", type => "byte_3", modifier => "+0", unit => "kPa"},
906             ] },
907             "External Test Equipment Configuration Information #2" => { command => "01 50",
908             result => [
909             {name => "Maximum value for Air Flow Rate from Mass Air Flow Sensor", type => "byte_0", modifier => "+0", unit => "g/s"}
910             ] },
911            
912             "Type of fuel currently being utilized by the vehicle" => { command => "01 51", result => [{type => "byte_0", modifier => "+0", unit => "",
913             alternatives => [
914             {value => 1, meaning => "Gasoline/petrol"},
915             {value => 2, meaning => "Methanol"},
916             {value => 3, meaning => "Ethanol"},
917             {value => 4, meaning => "Diesel"},
918             {value => 5, meaning => "Liquefied Petroleum Gas (LPG)"},
919             {value => 6, meaning => "Compressed Natural Gas (CNG)"},
920             {value => 7, meaning => "Propane"},
921             {value => 8, meaning => "Battery/electric"},
922             {value => 9, meaning => "Bi-fuel vehicle using gasoline"},
923             {value => 10, meaning => "Bi-fuel vehicle using methanol"},
924             {value => 11, meaning => "Bi-fuel vehicle using ethanol"},
925             {value => 12, meaning => "Bi-fuel vehicle using LPG"},
926             {value => 13, meaning => "Bi-fuel vehicle using CNG"},
927             {value => 14, meaning => "Bi-fuel vehicle using propane"},
928             {value => 15, meaning => "Bi-fuel vehicle using battery"}
929             ] }
930             ] },
931            
932             "Alcohol Fuel Percentage" => { command => "01 52", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
933             "Absolute Evap System Vapour Pressure" => { command => "01 53", result => [{type => "word_0", modifier => "/200", unit => "kPa"}] },
934             "Evap System Vapour Pressure" => { command => "01 54", result => [{type => "signed_word_0", modifier => "+1", unit => "Pa"}] },
935             "Short Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "01 55", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
936             "Long Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "01 56", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
937             "Short Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "01 57", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
938             "Long Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "01 58", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
939            
940             "Short Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "01 55", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
941             "Long Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "01 56", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
942             "Short Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "01 57", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
943             "Long Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "01 58", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
944            
945             "Fuel Rail Pressure (absolute)" => { command => "01 59", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
946             "Relative Accelerator Pedal Position" => { command => "01 5A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
947            
948            
949            
950             "02 PIDs supported (01-20)" => { command => "02 00", available => 1,
951             result => [
952             {name => "Freeze frame Monitor status since DTCs cleared", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
953             {name => "DTC that caused required freeze frame data storage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
954             {name => "Freeze frame Fuel systems status", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
955             {name => "Freeze frame Calculated LOAD Value!", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
956             {name => "Freeze frame Engine Coolant Temperature", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
957             {name => "Freeze frame Short Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
958             {name => "Freeze frame Long Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
959             {name => "Freeze frame Short Term Fuel Trim - Bank 2/4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
960            
961             {name => "Freeze frame Long Term Fuel Trim - Bank 2/4", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
962             {name => "Freeze frame Fuel Rail Pressure (gauge)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
963             {name => "Freeze frame Intake Manifold Absolute Pressure", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
964             {name => "Freeze frame Engine RPM", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
965             {name => "Freeze frame Vehicle Speed Sensor", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
966             {name => "Freeze frame Ignition Timing Advance for #1 Cylinder", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
967             {name => "Freeze frame Intake Air Temperature", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
968             {name => "Freeze frame Air Flow Rate from Mass Air Flow Sensor", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
969            
970             {name => "Freeze frame Absolute Throttle Position", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
971             {name => "Freeze frame Commanded Secondary Air Status", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
972             {name => "Freeze frame Location of oxygen sensors 13", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
973             {name => "Freeze frame Bank 1 - Sensor 1", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
974             {name => "Freeze frame Bank 1 - Sensor 2", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
975            
976             {name => "Freeze frame Bank 1 - Sensor 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
977             {name => "Freeze frame Bank 1 - Sensor 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
978             {name => "Freeze frame Bank 2 - Sensor 1 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
979            
980             {name => "Freeze frame Bank 2 - Sensor 2 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
981             {name => "Freeze frame Bank 2 - Sensor 3", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
982             {name => "Freeze frame Bank 2 - Sensor 4", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
983             {name => "Freeze frame Bank 3 - Sensor 2", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
984             {name => "Freeze frame Bank 4 - Sensor 1", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
985             {name => "Freeze frame Bank 4 - Sensor 2", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
986             {name => "Freeze frame OBD requirements to which vehicle is designed", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
987             {name => "Freeze frame Location of oxygen sensors 1D", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
988             {name => "Freeze frame Bank 2 - Sensor 1 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
989             {name => "Freeze frame Bank 2 - Sensor 2 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
990             {name => "Freeze frame Bank 3 - Sensor 1", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
991             {name => "Freeze frame Auxiliary Input Status", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
992             {name => "Freeze frame Time Since Engine Start", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
993             {name => "02 PIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
994             ] },
995            
996             "Freeze frame Monitor status since DTCs cleared" => { command => "02 01",
997             result => [
998             {name => "Freeze frame Number of DTCs stored in this ECU", type => "byte_0", modifier => "&127", unit => ""},
999             {name => "Freeze frame Malfunction Indicator Lamp (MIL) Status", type => "bool_0", modifier => "&128", unit => "off,on"},
1000             {name => "Freeze frame Misfire monitoring supported", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1001             {name => "Freeze frame Fuel system monitoring supported", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1002             {name => "Freeze frame Comprehensive component monitoring supported", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1003             {name => "Freeze frame Misfire monitoring complete", type => "bool_1", modifier => "&16", unit => "not completed, completed"},
1004             {name => "Freeze frame Fuel system monitoring complete", type => "bool_1", modifier => "&32", unit => "not completed, completed"},
1005             {name => "Freeze frame Comprehensive component monitoring complete", type => "bool_1", modifier => "&64", unit => "not completed, completed"},
1006             {name => "Freeze frame Catalyst monitoring supported", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1007             {name => "Freeze frame Heated catalyst monitoring supported", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1008             {name => "Freeze frame Evaporative system monitoring supported", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1009             {name => "Freeze frame Secondary air system monitoring supported", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1010             {name => "Freeze frame A/C system refrigerant monitoring supported", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1011             {name => "Freeze frame Oxygen sensor monitoring supported", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1012             {name => "Freeze frame Oxygen sensor heater monitoring supported", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1013             {name => "Freeze frame EGR system monitoring supported", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1014             {name => "Freeze frame Catalyst monitoring complete", type => "bool_3", modifier => "&1", unit => "not completed, completed"},
1015             {name => "Freeze frame Heated catalyst monitoring complete", type => "bool_3", modifier => "&2", unit => "not completed, completed"},
1016             {name => "Freeze frame Evaporative system monitoring complete", type => "bool_3", modifier => "&4", unit => "not completed, completed"},
1017             {name => "Freeze frame Secondary air system monitoring complete", type => "bool_3", modifier => "&8", unit => "not completed, completed"},
1018             {name => "Freeze frame A/C system refrigerant monitoring complete", type => "bool_3", modifier => "&16", unit => "not completed, completed"},
1019             {name => "Freeze frame Oxygen sensor monitoring complete", type => "bool_3", modifier => "&32", unit => "not completed, completed"},
1020             {name => "Freeze frame Oxygen sensor heater monitoring complete", type => "bool_3", modifier => "&64", unit => "not completed, completed"},
1021             {name => "Freeze frame EGR system monitoring complete", type => "bool_3", modifier => "&128", unit => "not completed, completed"},
1022             ] },
1023            
1024             "DTC that caused required freeze frame data storage" => { command => "02 02", result => [{type => "word_0", modifier => "+0", unit => ""}] },
1025            
1026             "Freeze frame Fuel systems status" => { command => "02 03",
1027             result => [
1028             {name => "Freeze frame Fuel system 1 status", type => "byte_0", modifier => "&31", unit => "",
1029             alternatives => [
1030             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
1031             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
1032             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
1033             {value => 8, meaning => "Open loop - due to detected system fault"},
1034             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
1035             ]
1036             },
1037             {name => "Freeze frame Fuel system 2 status", type => "byte_1", modifier => "&31", unit => "",
1038             alternatives => [
1039             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
1040             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
1041             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
1042             {value => 8, meaning => "Open loop - due to detected system fault"},
1043             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
1044             ]
1045             }
1046             ] },
1047            
1048             "Freeze frame Calculated LOAD Value!" => { command => "02 04", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1049             "Freeze frame Engine Coolant Temperature" => { command => "02 05", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
1050            
1051             "Freeze frame Short Term Fuel Trim - Bank 1/3" => { command => "02 06",
1052             result => [
1053             {name => "Freeze frame Short Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1054             {name => "Freeze frame Short Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1055             ] },
1056            
1057             "Freeze frame Long Term Fuel Trim - Bank 1/3" => { command => "02 07",
1058             result => [
1059             {name => "Freeze frame Long Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1060             {name => "Freeze frame Long Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1061             ] },
1062            
1063             "Freeze frame Short Term Fuel Trim - Bank 2/4" => { command => "02 08",
1064             result => [
1065             {name => "Freeze frame Short Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1066             {name => "Freeze frame Short Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1067             ] },
1068            
1069             "Freeze frame Long Term Fuel Trim - Bank 2/4" => { command => "02 09",
1070             result => [
1071             {name => "Freeze frame Long Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1072             {name => "Freeze frame Long Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1073             ] },
1074            
1075            
1076             "Freeze frame Fuel Rail Pressure (gauge)" => { command => "02 0A", result => [{type => "byte_0", modifier => "*3", unit => "kPa"}] },
1077             "Freeze frame Intake Manifold Absolute Pressure" => { command => "02 0B", result => [{type => "byte_0", modifier => "*1", unit => "kPa"}] },
1078             "Freeze frame Engine RPM" => { command => "02 0C", result => [{type => "word_0", modifier => "/4", unit => "RPM"}] },
1079             "Freeze frame Vehicle Speed Sensor" => { command => "02 0D", result => [{type => "byte_0", modifier => "+0", unit => "km/h"}] },
1080             "Freeze frame Ignition Timing Advance for #1 Cylinder" => { command => "02 0E", result => [{type => "signed_byte_0", modifier => "/2", unit => "°"}] },
1081             "Freeze frame Intake Air Temperature" => { command => "02 0F", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
1082             "Freeze frame Air Flow Rate from Mass Air Flow Sensor" => { command => "02 10", result => [{type => "word_0", modifier => "/100", unit => "g/s"}] },
1083             "Freeze frame Absolute Throttle Position" => { command => "02 11", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1084             "Freeze frame Commanded Secondary Air Status" => { command => "02 12", result => [{type => "byte_0", modifier => "*100/255", unit => "",
1085             alternatives => [
1086             {value => 1, meaning => "upstream of first catalytic converter"},
1087             {value => 2, meaning => "downstream of first catalytic converter inlet"},
1088             {value => 4, meaning => "atmosphere / off"}
1089             ] }
1090             ] },
1091            
1092             "Freeze frame Location of oxygen sensors 13" => { command => "02 13",
1093             result => [
1094             {name => "Freeze frame Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
1095             {name => "Freeze frame Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
1096             {name => "Freeze frame Bank 1 - Sensor 3 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
1097             {name => "Freeze frame Bank 1 - Sensor 4 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
1098             {name => "Freeze frame Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
1099             {name => "Freeze frame Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
1100             {name => "Freeze frame Bank 2 - Sensor 3 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
1101             {name => "Freeze frame Bank 2 - Sensor 4 present", type => "bool_0", modifier => "&128", unit => "not present,present"}
1102             ] },
1103            
1104             "Freeze frame Bank 1 - Sensor 1" => { command => "02 14",
1105             result => [
1106             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1107             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1108             ] },
1109            
1110             "Freeze frame Bank 1 - Sensor 2" => { command => "02 15",
1111             result => [
1112             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1113             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1114             ] },
1115            
1116             "Freeze frame Bank 1 - Sensor 3" => { command => "02 16",
1117             result => [
1118             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1119             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1120             ] },
1121            
1122             "Freeze frame Bank 1 - Sensor 4" => { command => "02 17",
1123             result => [
1124             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1125             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1126             ] },
1127            
1128             "Freeze frame Bank 2 - Sensor 1 13" => { command => "02 18",
1129             result => [
1130             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1131             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1132             ] },
1133            
1134             "Freeze frame Bank 2 - Sensor 2 13" => { command => "02 19",
1135             result => [
1136             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1137             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1138             ] },
1139            
1140             "Freeze frame Bank 2 - Sensor 3" => { command => "02 1A",
1141             result => [
1142             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1143             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1144             ] },
1145            
1146             "Freeze frame Bank 2 - Sensor 4" => { command => "02 1B",
1147             result => [
1148             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1149             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1150             ] },
1151            
1152            
1153             "Freeze frame Bank 2 - Sensor 1 1D" => { command => "02 16",
1154             result => [
1155             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1156             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1157             ] },
1158            
1159             "Freeze frame Bank 2 - Sensor 2 1D" => { command => "02 17",
1160             result => [
1161             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1162             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1163             ] },
1164            
1165             "Freeze frame Bank 3 - Sensor 1" => { command => "02 18",
1166             result => [
1167             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1168             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1169             ] },
1170            
1171             "Freeze frame Bank 3 - Sensor 2" => { command => "02 19",
1172             result => [
1173             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1174             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1175             ] },
1176            
1177             "Freeze frame Bank 4 - Sensor 1" => { command => "02 1A",
1178             result => [
1179             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1180             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1181             ] },
1182            
1183             "Freeze frame Bank 4 - Sensor 2" => { command => "02 1B",
1184             result => [
1185             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1186             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1187             ] },
1188            
1189            
1190             "Freeze frame OBD requirements to which vehicle is designed" => { command => "02 1C", result => [{type => "byte_0", modifier => "+0", unit => "",
1191             alternatives => [
1192             {value => 1, meaning => "OBD II (California ARB)"},
1193             {value => 2, meaning => "OBD (Federal EPA)"},
1194             {value => 3, meaning => "OBD and OBD II"},
1195             {value => 4, meaning => "OBD I"},
1196             {value => 5, meaning => "Not OBD compliant"},
1197             {value => 6, meaning => "EOBD"},
1198             {value => 7, meaning => "EOBD and OBD II"},
1199             {value => 8, meaning => "EOBD and OBD"},
1200             {value => 9, meaning => "EOBD, OBD and OBD II"},
1201             {value => 10, meaning => "JOBD"},
1202             {value => 11, meaning => "JOBD and OBD II"},
1203             {value => 12, meaning => "JOBD and EOBD"},
1204             {value => 13, meaning => "JOBD, EOBD, and OBD II"}
1205             ] }
1206             ] },
1207            
1208             "Freeze frame Location of oxygen sensors 1D" => { command => "02 1D",
1209             result => [
1210             {name => "Freeze frame Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
1211             {name => "Freeze frame Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
1212             {name => "Freeze frame Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
1213             {name => "Freeze frame Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
1214             {name => "Freeze frame Bank 3 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
1215             {name => "Freeze frame Bank 3 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
1216             {name => "Freeze frame Bank 4 - Sensor 1 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
1217             {name => "Freeze frame Bank 4 - Sensor 2 present", type => "bool_0", modifier => "&128", unit => "not present,present"},
1218             ] },
1219            
1220             "Freeze frame Auxiliary Input Status" => { command => "02 1E", result => [{name => "Freeze frame Power Take Off (PTO) Status", type => "bool_0", modifier => "&1", unit => "off,on"}] },
1221             "Freeze frame Time Since Engine Start" => { command => "02 1F", result => [{type => "word_0", modifier => "*10", unit => "s"}] },
1222            
1223             "02 PIDs supported (21-40)" => { command => "02 20",
1224             result => [
1225             {name => "Freeze frame Distance Travelled While MIL is Activated", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1226             {name => "Freeze frame Fuel Rail Pressure relative to manifold vacuum", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1227             {name => "Freeze frame Fuel Rail Pressure", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1228             {name => "Freeze frame Bank 1 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1229             {name => "Freeze frame Bank 1 - Sensor 2 (wide range O2S)", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1230            
1231             {name => "Freeze frame Bank 1 - Sensor 3 (wide range O2S)", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1232             {name => "Freeze frame Bank 1 - Sensor 4 (wide range O2S)", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1233             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 13", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1234             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 1D", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1235             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 1D", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1236             {name => "Freeze frame Bank 3 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1237            
1238             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 13", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1239             {name => "Freeze frame Bank 2 - Sensor 3 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1240             {name => "Freeze frame Bank 2 - Sensor 4 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1241             {name => "Freeze frame Bank 3 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1242             {name => "Freeze frame Bank 4 - Sensor 1 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1243             {name => "Freeze frame Bank 4 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1244            
1245             {name => "Freeze frame Commanded EGR", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1246             {name => "Freeze frame EGR Error", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1247             {name => "Freeze frame Commanded Evaporative Purge", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1248             {name => "Freeze frame Fuel Level Input", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1249             {name => "Freeze frame Number of warm-ups since diagnostic trouble codes cleared", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1250            
1251             {name => "Freeze frame Distance since diagnostic trouble codes cleared", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1252             {name => "Freeze frame Evap System Vapor Pressure", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1253             {name => "Freeze frame Barometric Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1254             {name => "Freeze frame Bank 1 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1255             {name => "Freeze frame Bank 1 - Sensor 2 (wide range O2S) current", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1256             {name => "Freeze frame Bank 1 - Sensor 3 (wide range O2S) current", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1257             {name => "Freeze frame Bank 1 - Sensor 4 (wide range O2S) current", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1258             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1259            
1260             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1261             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1262             {name => "Freeze frame Bank 3 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1263            
1264             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1265             {name => "Freeze frame Bank 2 - Sensor 3 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1266             {name => "Freeze frame Bank 2 - Sensor 4 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1267             {name => "Freeze frame Bank 3 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1268             {name => "Freeze frame Bank 4 - Sensor 1 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1269             {name => "Freeze frame Bank 4 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1270             {name => "Freeze frame Catalyst Temperature Bank 1, Sensor 1", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1271             {name => "Freeze frame Catalyst Temperature Bank 1, Sensor 2", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1272             {name => "Freeze frame Catalyst Temperature Bank 2, Sensor 1", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1273             {name => "Freeze frame Catalyst Temperature Bank 2, Sensor 2", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1274             {name => "02 PIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1275             ] },
1276            
1277             "Freeze frame Distance Travelled While MIL is Activated" => { command => "02 21", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
1278             "Freeze frame Fuel Rail Pressure relative to manifold vacuum" => { command => "02 22", result => [{type => "word_0", modifier => "*0.079", unit => "kPa"}] },
1279             "Freeze frame Fuel Rail Pressure" => { command => "02 23", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
1280            
1281             "Freeze frame Bank 1 - Sensor 1 (wide range O2S)" => { command => "02 24",
1282             result => [
1283             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1284             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1285             ] },
1286            
1287             "Freeze frame Bank 1 - Sensor 2 (wide range O2S)" => { command => "02 25",
1288             result => [
1289             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1290             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1291             ] },
1292            
1293             "Freeze frame Bank 1 - Sensor 3 (wide range O2S)" => { command => "02 26",
1294             result => [
1295             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1296             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1297             ] },
1298            
1299             "Freeze frame Bank 1 - Sensor 4 (wide range O2S)" => { command => "02 27",
1300             result => [
1301             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1302             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1303             ] },
1304            
1305             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 13" => { command => "02 28",
1306             result => [
1307             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1308             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1309             ] },
1310            
1311             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 13" => { command => "02 29",
1312             result => [
1313             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1314             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1315             ] },
1316            
1317             "Freeze frame Bank 2 - Sensor 3 (wide range O2S)" => { command => "02 2A",
1318             result => [
1319             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1320             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1321             ] },
1322            
1323             "Freeze frame Bank 2 - Sensor 4 (wide range O2S)" => { command => "02 2B",
1324             result => [
1325             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1326             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1327             ] },
1328            
1329            
1330             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 1D" => { command => "02 26",
1331             result => [
1332             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1333             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1334             ] },
1335            
1336             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 1D" => { command => "02 27",
1337             result => [
1338             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1339             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1340             ] },
1341            
1342             "Freeze frame Bank 3 - Sensor 1 (wide range O2S)" => { command => "02 28",
1343             result => [
1344             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1345             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1346             ] },
1347            
1348             "Freeze frame Bank 3 - Sensor 2 (wide range O2S)" => { command => "02 29",
1349             result => [
1350             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1351             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1352             ] },
1353            
1354             "Freeze frame Bank 4 - Sensor 1 (wide range O2S)" => { command => "02 2A",
1355             result => [
1356             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1357             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1358             ] },
1359            
1360             "Freeze frame Bank 4 - Sensor 2 (wide range O2S)" => { command => "02 2B",
1361             result => [
1362             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1363             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1364             ] },
1365            
1366             "Freeze frame Commanded EGR" => { command => "02 2C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1367             "Freeze frame EGR Error" => { command => "02 2D", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1368             "Freeze frame Commanded Evaporative Purge" => { command => "02 2E", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1369             "Freeze frame Fuel Level Input" => { command => "02 2F", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1370             "Freeze frame Number of warm-ups since diagnostic trouble codes cleared" => { command => "02 30", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
1371             "Freeze frame Distance since diagnostic trouble codes cleared" => { command => "02 31", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
1372             "Freeze frame Evap System Vapor Pressure" => { command => "02 32", result => [{type => "signed_word_0", modifier => "*0.25", unit => "Pa"}] },
1373             "Freeze frame Barometric Pressure" => { command => "02 33", result => [{type => "byte_0", modifier => "+0", unit => "kPa"}] },
1374            
1375             "Freeze frame Bank 1 - Sensor 1 (wide range O2S) current" => { command => "02 34",
1376             result => [
1377             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1378             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1379             ] },
1380            
1381             "Freeze frame Bank 1 - Sensor 2 (wide range O2S) current" => { command => "02 35",
1382             result => [
1383             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1384             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1385             ] },
1386            
1387             "Freeze frame Bank 1 - Sensor 3 (wide range O2S) current" => { command => "02 36",
1388             result => [
1389             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1390             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1391             ] },
1392            
1393             "Freeze frame Bank 1 - Sensor 4 (wide range O2S) current" => { command => "02 37",
1394             result => [
1395             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1396             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1397             ] },
1398            
1399             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 13" => { command => "02 38",
1400             result => [
1401             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1402             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1403             ] },
1404            
1405             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 13" => { command => "02 39",
1406             result => [
1407             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1408             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1409             ] },
1410            
1411             "Freeze frame Bank 2 - Sensor 3 (wide range O2S) current" => { command => "02 3A",
1412             result => [
1413             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1414             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1415             ] },
1416            
1417             "Freeze frame Bank 2 - Sensor 4 (wide range O2S) current" => { command => "02 3B",
1418             result => [
1419             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1420             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1421             ] },
1422            
1423            
1424             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 1D" => { command => "02 36",
1425             result => [
1426             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1427             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1428             ] },
1429            
1430             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 1D" => { command => "02 37",
1431             result => [
1432             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1433             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1434             ] },
1435            
1436             "Freeze frame Bank 3 - Sensor 1 (wide range O2S) current" => { command => "02 38",
1437             result => [
1438             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1439             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1440             ] },
1441            
1442             "Freeze frame Bank 3 - Sensor 2 (wide range O2S) current" => { command => "02 39",
1443             result => [
1444             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1445             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1446             ] },
1447            
1448             "Freeze frame Bank 4 - Sensor 1 (wide range O2S) current" => { command => "02 3A",
1449             result => [
1450             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1451             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1452             ] },
1453            
1454             "Freeze frame Bank 4 - Sensor 2 (wide range O2S) current" => { command => "02 3B",
1455             result => [
1456             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1457             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1458             ] },
1459            
1460             "Freeze frame Catalyst Temperature Bank 1, Sensor 1" => { command => "02 3C", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1461             "Freeze frame Catalyst Temperature Bank 1, Sensor 2" => { command => "02 3D", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1462             "Freeze frame Catalyst Temperature Bank 2, Sensor 1" => { command => "02 3E", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1463             "Freeze frame Catalyst Temperature Bank 2, Sensor 2" => { command => "02 3F", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1464            
1465             "02 PIDs supported (41-60)" => { command => "02 40",
1466             result => [
1467             {name => "Freeze frame Monitor status this driving cycle", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1468             {name => "Freeze frame Control Module Voltage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1469             {name => "Freeze frame Absolute Load Value", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1470             {name => "Freeze frame Commanded Equivalence Ratio", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1471             {name => "Freeze frame Relative Throttle Position", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1472             {name => "Freeze frame Ambiant Air Temperature", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1473             {name => "Freeze frame Absolute Throttle Position B", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1474             {name => "Freeze frame Absolute Throttle Position C", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1475            
1476             {name => "Freeze frame Absolute Throttle Position D", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1477             {name => "Freeze frame Absolute Throttle Position E", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1478             {name => "Freeze frame Absolute Throttle Position F", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1479             {name => "Freeze frame Commanded Throttle Actuator Control", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1480             {name => "Freeze frame Minutes run by the engine while MIL activated", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1481             {name => "Freeze frame Time since diagnostic trouble codes cleared", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1482             {name => "Freeze frame External Test Equipment Configuration Information #1", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1483             {name => "Freeze frame External Test Equipment Configuration Information #2", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1484            
1485             {name => "Freeze frame Type of fuel currently being utilized by the vehicle", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1486             {name => "Freeze frame Alcohol Fuel Percentage", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1487             {name => "Freeze frame Absolute Evap System Vapour Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1488             {name => "Freeze frame Evap System Vapour Pressure", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1489             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1490             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1491             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1492             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1493             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1494             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1495             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1496             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1497            
1498             {name => "Freeze frame Fuel Rail Pressure (absolute)", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1499             {name => "Freeze frame Relative Accelerator Pedal Position", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1500             # {name => "Freeze frame ", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1501             # {name => "Freeze frame ", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1502             # {name => "Freeze frame ", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1503             # {name => "Freeze frame ", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1504             # {name => "Freeze frame ", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1505             # {name => "02 PIDs supported (61-80)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1506             ] },
1507            
1508            
1509             "Freeze frame Monitor status this driving cycle" => { command => "02 41",
1510             result => [
1511             {name => "Freeze frame Misfire monitoring Enable Status", type => "bool_1", modifier => "&1", unit => "not enabled,enabled"},
1512             {name => "Freeze frame Fuel system monitoring Enable Status", type => "bool_1", modifier => "&2", unit => "not enabled,enabled"},
1513             {name => "Freeze frame Comprehensive component monitoring Enable Status", type => "bool_1", modifier => "&4", unit => "not enabled,enabled"},
1514             {name => "Freeze frame Misfire monitoring Completion Status", type => "bool_1", modifier => "&16", unit => "not completed,completed"},
1515             {name => "Freeze frame Fuel system monitoring Completion Status", type => "bool_1", modifier => "&32", unit => "not completed,completed"},
1516             {name => "Freeze frame Comprehensive component monitoring Completion Status", type => "bool_1", modifier => "&64", unit => "not completed,completed"},
1517             {name => "Freeze frame Catalyst monitoring Enable Status", type => "bool_2", modifier => "&1", unit => "not enabled,enabled"},
1518             {name => "Freeze frame Heated catalyst monitoring Enable Status", type => "bool_2", modifier => "&2", unit => "not enabled,enabled"},
1519             {name => "Freeze frame Evaporative system monitoring Enable Status", type => "bool_2", modifier => "&4", unit => "not enabled,enabled"},
1520             {name => "Freeze frame Secondary air system monitoring Enable Status", type => "bool_2", modifier => "&8", unit => "not enabled,enabled"},
1521             {name => "Freeze frame A/C system refrigerant monitoring Enable Status", type => "bool_2", modifier => "&16", unit => "not enabled,enabled"},
1522             {name => "Freeze frame Oxygen sensor monitoring Enable Status", type => "bool_2", modifier => "&32", unit => "not enabled,enabled"},
1523             {name => "Freeze frame Oxygen sensor heater monitoring Enable Status", type => "bool_2", modifier => "&64", unit => "not enabled,enabled"},
1524             {name => "Freeze frame EGR monitoring Enable Status", type => "bool_2", modifier => "&128", unit => "not enabled,enabled"},
1525             {name => "Freeze frame Catalyst monitoring Completion Status", type => "bool_3", modifier => "&1", unit => "not completed,completed"},
1526             {name => "Freeze frame Heated catalyst monitoring Completion Status", type => "bool_3", modifier => "&2", unit => "not completed,completed"},
1527             {name => "Freeze frame Evaporative system monitoring Completion Status", type => "bool_3", modifier => "&4", unit => "not completed,completed"},
1528             {name => "Freeze frame Secondary air system monitoring Completion Status", type => "bool_3", modifier => "&8", unit => "not completed,completed"},
1529             {name => "Freeze frame A/C system refrigerant monitoring Completion Status", type => "bool_3", modifier => "&16", unit => "not completed,completed"},
1530             {name => "Freeze frame Oxygen sensor monitoring Completion Status", type => "bool_3", modifier => "&32", unit => "not completed,completed"},
1531             {name => "Freeze frame Oxygen sensor heater monitoring Completion Status", type => "bool_3", modifier => "&64", unit => "not completed,completed"},
1532             {name => "Freeze frame EGR monitoring Completion Status", type => "bool_3", modifier => "&128", unit => "not completed,completed"}
1533             ] },
1534            
1535             "Freeze frame Control Module Voltage" => { command => "02 42", result => [{type => "word_0", modifier => "*0.001", unit => "V"}] },
1536             "Freeze frame Absolute Load Value" => { command => "02 43", result => [{type => "word_0", modifier => "*100/255", unit => "%"}] },
1537             "Freeze frame Commanded Equivalence Ratio" => { command => "02 44", result => [{type => "word_0", modifier => "*0.0000305", unit => ""}] },
1538             "Freeze frame Relative Throttle Position" => { command => "02 45", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1539             "Freeze frame Ambiant Air Temperature" => { command => "02 46", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
1540             "Freeze frame Absolute Throttle Position B" => { command => "02 47", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1541             "Freeze frame Absolute Throttle Position C" => { command => "02 48", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1542             "Freeze frame Accelerator Pedal Position D" => { command => "02 49", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1543             "Freeze frame Accelerator Pedal Position E" => { command => "02 4A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1544             "Freeze frame Accelerator Pedal Position F" => { command => "02 4B", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1545             "Freeze frame Commanded Throttle Actuator Control" => { command => "02 4C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1546             "Freeze frame Minutes run by the engine while MIL activated" => { command => "02 4D", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
1547             "Freeze frame Time since diagnostic trouble codes cleared" => { command => "02 4E", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
1548             "Freeze frame External Test Equipment Configuration Information #1" => { command => "02 4F",
1549             result => [
1550             {name => "Freeze frame Maximum value for Equivalence Ratio", type => "byte_0", modifier => "+0", unit => ""},
1551             {name => "Freeze frame Maximum value for Oxygen Sensor Voltage", type => "byte_1", modifier => "+0", unit => "V"},
1552             {name => "Freeze frame Maximum value for Oxygen Sensor Current", type => "byte_2", modifier => "+0", unit => "mA"},
1553             {name => "Freeze frame Maximum value for Intake Manifold Absolute Pressure", type => "byte_3", modifier => "+0", unit => "kPa"},
1554             ] },
1555             "Freeze frame External Test Equipment Configuration Information #2" => { command => "02 50",
1556             result => [
1557             {name => "Freeze frame Maximum value for Air Flow Rate from Mass Air Flow Sensor", type => "byte_0", modifier => "+0", unit => "g/s"}
1558             ] },
1559            
1560             "Freeze frame Type of fuel currently being utilized by the vehicle" => { command => "02 51", result => [{type => "byte_0", modifier => "+0", unit => "",
1561             alternatives => [
1562             {value => 1, meaning => "Gasoline/petrol"},
1563             {value => 2, meaning => "Methanol"},
1564             {value => 3, meaning => "Ethanol"},
1565             {value => 4, meaning => "Diesel"},
1566             {value => 5, meaning => "Liquefied Petroleum Gas (LPG)"},
1567             {value => 6, meaning => "Compressed Natural Gas (CNG)"},
1568             {value => 7, meaning => "Propane"},
1569             {value => 8, meaning => "Battery/electric"},
1570             {value => 9, meaning => "Bi-fuel vehicle using gasoline"},
1571             {value => 10, meaning => "Bi-fuel vehicle using methanol"},
1572             {value => 11, meaning => "Bi-fuel vehicle using ethanol"},
1573             {value => 12, meaning => "Bi-fuel vehicle using LPG"},
1574             {value => 13, meaning => "Bi-fuel vehicle using CNG"},
1575             {value => 14, meaning => "Bi-fuel vehicle using propane"},
1576             {value => 15, meaning => "Bi-fuel vehicle using battery"}
1577             ] }
1578             ] },
1579            
1580             "Freeze frame Alcohol Fuel Percentage" => { command => "02 52", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1581             "Freeze frame Absolute Evap System Vapour Pressure" => { command => "02 53", result => [{type => "word_0", modifier => "/200", unit => "kPa"}] },
1582             "Freeze frame Evap System Vapour Pressure" => { command => "02 54", result => [{type => "signed_word_0", modifier => "+1", unit => "Pa"}] },
1583             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "02 55", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1584             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "02 56", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1585             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "02 57", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1586             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "02 58", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1587            
1588             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "02 55", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1589             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "02 56", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1590             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "02 57", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1591             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "02 58", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1592            
1593             "Freeze frame Fuel Rail Pressure (absolute)" => { command => "02 59", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
1594             "Freeze frame Relative Accelerator Pedal Position" => { command => "02 5A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1595            
1596            
1597             "Emission-related diagnostic trouble codes" => { command => "03", available => 1,
1598             result => [
1599             {name => "DTC#1", type => "word_0", modifier => "+0", unit => ""},
1600             {name => "DTC#2", type => "word_1", modifier => "+0", unit => ""},
1601             {name => "DTC#3", type => "word_2", modifier => "+0", unit => ""},
1602             ] },
1603            
1604             "05 TIDs supported (01-20)" => { command => "05 00",
1605             result => [
1606             {name => "Rich to lean sensor threshold voltage", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1607             {name => "Lean to rich sensor threshold voltage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1608             {name => "Low sensor voltage for switch time calculation", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1609             {name => "High sensor voltage for switch time calculation", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1610             {name => "Rich to lean sensor switch time", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1611             {name => "Lean to rich sensor switch time", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1612             {name => "Minimum sensor voltage for test cycle", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1613             {name => "Maximum sensor voltage for test cycle", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1614            
1615             {name => "Time between sensor transitions", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1616             {name => "Sensor period", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1617             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1618             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1619             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1620             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1621             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1622             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1623            
1624             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1625             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1626             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1627             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1628             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1629             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1630             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1631             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1632            
1633             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1634             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1635             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1636             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1637             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1638             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1639             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1640             # {name => "05 TIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1641             ] },
1642            
1643             "Rich to lean sensor threshold voltage" => { command => "05 01", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1644             "Lean to rich sensor threshold voltage" => { command => "05 02", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1645             "Low sensor voltage for switch time calculation" => { command => "05 03", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1646             "High sensor voltage for switch time calculation" => { command => "05 04", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1647            
1648             "Rich to lean sensor switch time" => { command => "05 05",
1649             result => [
1650             {type => "byte_0", modifier => "*0.004", unit => "s"},
1651             {name => "Rich to lean sensor switch time - low limit", type => "byte_1", modifier => "*0.004", unit => "s"},
1652             {name => "Rich to lean sensor switch time - high limit", type => "byte_2", modifier => "*0.004", unit => "s"},
1653             ] },
1654            
1655             "Lean to rich sensor switch time" => { command => "05 06",
1656             result => [
1657             {type => "byte_0", modifier => "*0.004", unit => "s"},
1658             {name => "Lean to rich sensor switch time - low limit", type => "byte_1", modifier => "*0.004", unit => "s"},
1659             {name => "Lean to rich sensor switch time - high limit", type => "byte_2", modifier => "*0.004", unit => "s"},
1660             ] },
1661            
1662             "Minimum sensor voltage for test cycle" => { command => "05 07",
1663             result => [
1664             {type => "byte_0", modifier => "*0.005", unit => "V"},
1665             {name => "Minimum sensor voltage for test cycle - low limit", type => "byte_1", modifier => "*0.005", unit => "V"},
1666             {name => "Minimum sensor voltage for test cycle - high limit", type => "byte_2", modifier => "*0.005", unit => "V"},
1667             ] },
1668            
1669             "Maximum sensor voltage for test cycle" => { command => "05 08",
1670             result => [
1671             {type => "byte_0", modifier => "*0.005", unit => "V"},
1672             {name => "Maximum sensor voltage for test cycle - low limit", type => "byte_1", modifier => "*0.005", unit => "V"},
1673             {name => "Maximum sensor voltage for test cycle - high limit", type => "byte_2", modifier => "*0.005", unit => "V"},
1674             ] },
1675            
1676             "Time between sensor transitions" => { command => "05 09",
1677             result => [
1678             {type => "byte_0", modifier => "*0.04", unit => "s"},
1679             {name => "Time between sensor transitions - low limit", type => "byte_1", modifier => "*0.04", unit => "s"},
1680             {name => "Time between sensor transitions - high limit", type => "byte_2", modifier => "*0.04", unit => "s"},
1681             ] },
1682            
1683             "Sensor period" => { command => "05 0A",
1684             result => [
1685             {type => "byte_0", modifier => "*0.04", unit => "s"},
1686             {name => "Sensor period - low limit", type => "byte_1", modifier => "*0.04", unit => "s"},
1687             {name => "Sensor period - high limit", type => "byte_2", modifier => "*0.04", unit => "s"},
1688             ] },
1689            
1690            
1691             "06 MIDs supported (01-20)" => { command => "06 00",
1692             result => [
1693             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1694             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1695             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1696             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1697             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 1", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1698             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 2", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1699             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1700             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1701            
1702             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 1", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1703             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 2", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1704             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 3", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1705             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 4", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1706             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 1", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1707             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 2", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1708             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 3", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1709             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 4", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1710            
1711             # 11 -1F reserved by ISO/SAE
1712             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1713             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1714             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1715             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1716             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1717             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1718             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1719             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1720            
1721             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1722             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1723             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1724             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1725             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1726             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1727             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1728             {name => "06 MIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1729             ] },
1730            
1731             "Oxygen Sensor Monitor Bank 1 - Sensor 1" => { command => "06 01", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1732             "Oxygen Sensor Monitor Bank 1 - Sensor 2" => { command => "06 02", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1733             "Oxygen Sensor Monitor Bank 1 - Sensor 3" => { command => "06 03", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1734             "Oxygen Sensor Monitor Bank 1 - Sensor 4" => { command => "06 04", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1735             "Oxygen Sensor Monitor Bank 2 - Sensor 1" => { command => "06 05", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1736             "Oxygen Sensor Monitor Bank 2 - Sensor 2" => { command => "06 06", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1737             "Oxygen Sensor Monitor Bank 2 - Sensor 3" => { command => "06 07", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1738             "Oxygen Sensor Monitor Bank 2 - Sensor 4" => { command => "06 08", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1739             "Oxygen Sensor Monitor Bank 3 - Sensor 1" => { command => "06 09", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1740             "Oxygen Sensor Monitor Bank 3 - Sensor 2" => { command => "06 0A", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1741             "Oxygen Sensor Monitor Bank 3 - Sensor 3" => { command => "06 0B", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1742             "Oxygen Sensor Monitor Bank 3 - Sensor 4" => { command => "06 0C", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1743             "Oxygen Sensor Monitor Bank 4 - Sensor 1" => { command => "06 0D", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1744             "Oxygen Sensor Monitor Bank 4 - Sensor 2" => { command => "06 0E", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1745             "Oxygen Sensor Monitor Bank 4 - Sensor 3" => { command => "06 0F", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1746             "Oxygen Sensor Monitor Bank 4 - Sensor 4" => { command => "06 10", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1747            
1748             "06 MIDs supported (21-40)" => { command => "06 20",
1749             result => [
1750             {name => "Catalyst Monitor Bank 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1751             {name => "Catalyst Monitor Bank 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1752             {name => "Catalyst Monitor Bank 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1753             {name => "Catalyst Monitor Bank 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1754             # {name => "", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1755             # {name => "", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1756             # {name => "", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1757             # {name => "", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1758            
1759             # {name => "", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1760             # {name => "", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1761             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1762             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1763             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1764             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1765             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1766             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1767            
1768             {name => "EGR Monitor Bank 1", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1769             {name => "EGR Monitor Bank 2", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1770             {name => "EGR Monitor Bank 3", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1771             {name => "EGR Monitor Bank 4", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1772             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1773             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1774             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1775             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1776            
1777             {name => "EVAP Monitor (Cap Off)", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1778             {name => "EVAP Monitor (0,090)", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1779             {name => "EVAP Monitor (0,040)", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1780             {name => "EVAP Monitor (0,020)", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1781             {name => "Purge Flow Monitor", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1782             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1783             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1784             {name => "06 MIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1785             ] },
1786            
1787             "Catalyst Monitor Bank 1" => { command => "06 21", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1788             "Catalyst Monitor Bank 2" => { command => "06 22", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1789             "Catalyst Monitor Bank 3" => { command => "06 23", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1790             "Catalyst Monitor Bank 4" => { command => "06 24", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1791            
1792             "EGR Monitor Bank 1" => { command => "06 31", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1793             "EGR Monitor Bank 2" => { command => "06 32", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1794             "EGR Monitor Bank 3" => { command => "06 33", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1795             "EGR Monitor Bank 4" => { command => "06 34", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1796            
1797             "EVAP Monitor (Cap Off)" => { command => "06 39", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1798             "EVAP Monitor (0,090)" => { command => "06 3A", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1799             "EVAP Monitor (0,040)" => { command => "06 3B", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1800             "EVAP Monitor (0,020)" => { command => "06 3C", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1801             "Purge Flow Monitor" => { command => "06 3D", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1802            
1803            
1804             "06 MIDs supported (41-60)" => { command => "06 40",
1805             result => [
1806             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1807             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1808             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1809             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1810             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 1", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1811             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 2", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1812             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1813             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1814            
1815             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 1", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1816             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 2", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1817             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 3", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1818             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 4", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1819             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 1", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1820             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 2", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1821             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 3", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1822             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 4", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1823            
1824             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1825             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1826             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1827             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1828             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1829             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1830             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1831             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1832            
1833             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1834             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1835             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1836             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1837             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1838             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1839             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1840             {name => "06 MIDs supported (61-80)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1841             ] },
1842            
1843             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 1" => { command => "06 41", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1844             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 2" => { command => "06 42", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1845             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 3" => { command => "06 43", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1846             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 4" => { command => "06 44", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1847             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 1" => { command => "06 45", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1848             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 2" => { command => "06 46", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1849             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 3" => { command => "06 47", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1850             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 4" => { command => "06 48", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1851             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 1" => { command => "06 49", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1852             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 2" => { command => "06 4A", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1853             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 3" => { command => "06 4B", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1854             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 4" => { command => "06 4C", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1855             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 1" => { command => "06 4D", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1856             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 2" => { command => "06 4E", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1857             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 3" => { command => "06 4F", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1858             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 4" => { command => "06 50", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1859            
1860            
1861            
1862             "06 MIDs supported (61-80)" => { command => "06 60",
1863             result => [
1864             {name => "Heated Catalyst Monitor Bank 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1865             {name => "Heated Catalyst Monitor Bank 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1866             {name => "Heated Catalyst Monitor Bank 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1867             {name => "Heated Catalyst Monitor Bank 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1868             # {name => "", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1869             # {name => "", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1870             # {name => "", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1871             # {name => "", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1872            
1873             # {name => "", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1874             # {name => "", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1875             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1876             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1877             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1878             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1879             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1880             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1881            
1882             {name => "Secondary Air Monitor 1", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1883             {name => "Secondary Air Monitor 2", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1884             {name => "Secondary Air Monitor 3", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1885             {name => "Secondary Air Monitor 4", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1886             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1887             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1888             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1889             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1890            
1891             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1892             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1893             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1894             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1895             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1896             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1897             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1898             {name => "06 MIDs supported (81-A0)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1899             ] },
1900            
1901             "Heated Catalyst Monitor Bank 1" => { command => "06 61", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1902             "Heated Catalyst Monitor Bank 2" => { command => "06 62", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1903             "Heated Catalyst Monitor Bank 3" => { command => "06 63", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1904             "Heated Catalyst Monitor Bank 4" => { command => "06 64", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1905            
1906             "Secondary Air Monitor 1" => { command => "06 71", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1907             "Secondary Air Monitor 2" => { command => "06 72", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1908             "Secondary Air Monitor 3" => { command => "06 73", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1909             "Secondary Air Monitor 4" => { command => "06 74", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1910            
1911             "06 MIDs supported (81-A0)" => { command => "06 80",
1912             result => [
1913             {name => "Fuel System Monitor Bank 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1914             {name => "Fuel System Monitor Bank 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1915             {name => "Fuel System Monitor Bank 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1916             {name => "Fuel System Monitor Bank 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1917             # {name => "", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1918             # {name => "", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1919             # {name => "", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1920             # {name => "", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1921            
1922             # {name => "", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1923             # {name => "", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1924             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1925             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1926             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1927             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1928             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1929             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1930            
1931             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1932             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1933             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1934             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1935             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1936             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1937             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1938             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1939            
1940             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1941             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1942             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1943             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1944             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1945             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1946             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1947             {name => "06 MIDs supported (A1-C0)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1948             ] },
1949            
1950             "Fuel System Monitor Bank 1" => { command => "06 81", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1951             "Fuel System Monitor Bank 2" => { command => "06 82", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1952             "Fuel System Monitor Bank 3" => { command => "06 83", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1953             "Fuel System Monitor Bank 4" => { command => "06 84", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1954            
1955            
1956             "06 MIDs supported (A1-C0)" => { command => "06 A0",
1957             result => [
1958             {name => "Misfire Monitor General Data", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1959             {name => "Misfire Cylinder 1 Data", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1960             {name => "Misfire Cylinder 2 Data", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1961             {name => "Misfire Cylinder 3 Data", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1962             {name => "Misfire Cylinder 4 Data", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1963             {name => "Misfire Cylinder 5 Data", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1964             {name => "Misfire Cylinder 6 Data", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1965             {name => "Misfire Cylinder 7 Data", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1966            
1967             {name => "Misfire Cylinder 8 Data", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1968             {name => "Misfire Cylinder 9 Data", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1969             {name => "Misfire Cylinder 10 Data", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1970             {name => "Misfire Cylinder 11 Data", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1971             {name => "Misfire Cylinder 12 Data", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1972             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1973             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1974             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1975            
1976             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1977             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1978             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1979             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1980             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1981             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1982             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1983             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1984            
1985             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1986             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1987             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1988             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1989             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1990             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1991             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1992             {name => "06 MIDs supported (C1-E0)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1993             ] },
1994            
1995             "Misfire Monitor General Data" => { command => "06 A1", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1996             "Misfire Cylinder 1 Data" => { command => "06 A2", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1997             "Misfire Cylinder 2 Data" => { command => "06 A3", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1998             "Misfire Cylinder 3 Data" => { command => "06 A4", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1999             "Misfire Cylinder 4 Data" => { command => "06 A5", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2000             "Misfire Cylinder 5 Data" => { command => "06 A6", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2001             "Misfire Cylinder 6 Data" => { command => "06 A7", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2002             "Misfire Cylinder 7 Data" => { command => "06 A8", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2003             "Misfire Cylinder 8 Data" => { command => "06 A9", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2004             "Misfire Cylinder 9 Data" => { command => "06 AA", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2005             "Misfire Cylinder 10 Data" => { command => "06 AB", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2006             "Misfire Cylinder 11 Data" => { command => "06 AC", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2007             "Misfire Cylinder 12 Data" => { command => "06 AD", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2008            
2009            
2010            
2011             "06 MIDs supported (C1-E0)" => { command => "06 C0",
2012             result => [
2013             # {name => "", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
2014             # {name => "", type => "bool_0", modifier => "&64", unit => ""},
2015             # {name => "", type => "bool_0", modifier => "&32", unit => ""},
2016             # {name => "", type => "bool_0", modifier => "&16", unit => ""},
2017             # {name => "", type => "bool_0", modifier => "&8", unit => ""},
2018             # {name => "", type => "bool_0", modifier => "&4", unit => ""},
2019             # {name => "", type => "bool_0", modifier => "&2", unit => ""},
2020             # {name => "", type => "bool_0", modifier => "&1", unit => ""},
2021            
2022             # {name => "", type => "bool_1", modifier => "&128", unit => ""},
2023             # {name => "", type => "bool_1", modifier => "&64", unit => ""},
2024             # {name => "", type => "bool_1", modifier => "&32", unit => ""},
2025             # {name => "", type => "bool_1", modifier => "&16", unit => ""},
2026             # {name => "", type => "bool_1", modifier => "&8", unit => ""},
2027             # {name => "", type => "bool_1", modifier => "&4", unit => ""},
2028             # {name => "", type => "bool_1", modifier => "&2", unit => ""},
2029             # {name => "", type => "bool_1", modifier => "&1", unit => ""},
2030            
2031             # {name => "", type => "bool_2", modifier => "&128", unit => ""},
2032             # {name => "", type => "bool_2", modifier => "&64", unit => ""},
2033             # {name => "", type => "bool_2", modifier => "&32", unit => ""},
2034             # {name => "", type => "bool_2", modifier => "&16", unit => ""},
2035             # {name => "", type => "bool_2", modifier => "&8", unit => ""},
2036             # {name => "", type => "bool_2", modifier => "&4", unit => ""},
2037             # {name => "", type => "bool_2", modifier => "&2", unit => ""},
2038             # {name => "", type => "bool_2", modifier => "&1", unit => ""},
2039            
2040             # {name => "", type => "bool_3", modifier => "&128", unit => ""},
2041             # {name => "", type => "bool_3", modifier => "&64", unit => ""},
2042             # {name => "", type => "bool_3", modifier => "&32", unit => ""},
2043             # {name => "", type => "bool_3", modifier => "&16", unit => ""},
2044             # {name => "", type => "bool_3", modifier => "&8", unit => ""},
2045             # {name => "", type => "bool_3", modifier => "&4", unit => ""},
2046             # {name => "", type => "bool_3", modifier => "&2", unit => ""},
2047             {name => "06 MIDs supported (E1-FF)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
2048             ] },
2049            
2050             "06 MIDs supported (E1-FF)" => { command => "06 E0",
2051             result => [
2052             # {name => "Vehicle manufacturer defined OBDMID E1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
2053             # {name => "Vehicle manufacturer defined OBDMID E2", type => "bool_0", modifier => "&64", unit => ""},
2054             # {name => "Vehicle manufacturer defined OBDMID E3", type => "bool_0", modifier => "&32", unit => ""},
2055             # {name => "Vehicle manufacturer defined OBDMID E4", type => "bool_0", modifier => "&16", unit => ""},
2056             # {name => "Vehicle manufacturer defined OBDMID E5", type => "bool_0", modifier => "&8", unit => ""},
2057             # {name => "Vehicle manufacturer defined OBDMID E6", type => "bool_0", modifier => "&4", unit => ""},
2058             # {name => "Vehicle manufacturer defined OBDMID E7", type => "bool_0", modifier => "&2", unit => ""},
2059             # {name => "Vehicle manufacturer defined OBDMID E8", type => "bool_0", modifier => "&1", unit => ""},
2060            
2061             # {name => "Vehicle manufacturer defined OBDMID E9", type => "bool_1", modifier => "&128", unit => ""},
2062             # {name => "Vehicle manufacturer defined OBDMID EA", type => "bool_1", modifier => "&64", unit => ""},
2063             # {name => "Vehicle manufacturer defined OBDMID EB", type => "bool_1", modifier => "&32", unit => ""},
2064             # {name => "Vehicle manufacturer defined OBDMID EC", type => "bool_1", modifier => "&16", unit => ""},
2065             # {name => "Vehicle manufacturer defined OBDMID ED", type => "bool_1", modifier => "&8", unit => ""},
2066             # {name => "Vehicle manufacturer defined OBDMID EE", type => "bool_1", modifier => "&4", unit => ""},
2067             # {name => "Vehicle manufacturer defined OBDMID EF", type => "bool_1", modifier => "&2", unit => ""},
2068             # {name => "Vehicle manufacturer defined OBDMID F0", type => "bool_1", modifier => "&1", unit => ""},
2069            
2070             # {name => "Vehicle manufacturer defined OBDMID F1", type => "bool_2", modifier => "&128", unit => ""},
2071             # {name => "Vehicle manufacturer defined OBDMID F2", type => "bool_2", modifier => "&64", unit => ""},
2072             # {name => "Vehicle manufacturer defined OBDMID F3", type => "bool_2", modifier => "&32", unit => ""},
2073             # {name => "Vehicle manufacturer defined OBDMID F4", type => "bool_2", modifier => "&16", unit => ""},
2074             # {name => "Vehicle manufacturer defined OBDMID F5", type => "bool_2", modifier => "&8", unit => ""},
2075             # {name => "Vehicle manufacturer defined OBDMID F6", type => "bool_2", modifier => "&4", unit => ""},
2076             # {name => "Vehicle manufacturer defined OBDMID F7", type => "bool_2", modifier => "&2", unit => ""},
2077             # {name => "Vehicle manufacturer defined OBDMID F8", type => "bool_2", modifier => "&1", unit => ""},
2078            
2079             # {name => "Vehicle manufacturer defined OBDMID F9", type => "bool_3", modifier => "&128", unit => ""},
2080             # {name => "Vehicle manufacturer defined OBDMID FA", type => "bool_3", modifier => "&64", unit => ""},
2081             # {name => "Vehicle manufacturer defined OBDMID FB", type => "bool_3", modifier => "&32", unit => ""},
2082             # {name => "Vehicle manufacturer defined OBDMID FC", type => "bool_3", modifier => "&16", unit => ""},
2083             # {name => "Vehicle manufacturer defined OBDMID FD", type => "bool_3", modifier => "&8", unit => ""},
2084             # {name => "Vehicle manufacturer defined OBDMID FE", type => "bool_3", modifier => "&4", unit => ""},
2085             # {name => "Vehicle manufacturer defined OBDMID FF", type => "bool_3", modifier => "&2", unit => ""},
2086             ] },
2087            
2088             "Vehicle manufacturer defined OBDMID E1" => { command => "06 E1", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2089             "Vehicle manufacturer defined OBDMID E2" => { command => "06 E2", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2090             "Vehicle manufacturer defined OBDMID E3" => { command => "06 E3", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2091             "Vehicle manufacturer defined OBDMID E4" => { command => "06 E4", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2092             "Vehicle manufacturer defined OBDMID E5" => { command => "06 E5", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2093             "Vehicle manufacturer defined OBDMID E6" => { command => "06 E6", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2094             "Vehicle manufacturer defined OBDMID E7" => { command => "06 E7", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2095             "Vehicle manufacturer defined OBDMID E8" => { command => "06 E8", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2096             "Vehicle manufacturer defined OBDMID E9" => { command => "06 E9", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2097             "Vehicle manufacturer defined OBDMID EA" => { command => "06 EA", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2098             "Vehicle manufacturer defined OBDMID EB" => { command => "06 EB", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2099             "Vehicle manufacturer defined OBDMID EC" => { command => "06 EC", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2100             "Vehicle manufacturer defined OBDMID ED" => { command => "06 ED", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2101             "Vehicle manufacturer defined OBDMID EE" => { command => "06 EE", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2102             "Vehicle manufacturer defined OBDMID EF" => { command => "06 EF", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2103             "Vehicle manufacturer defined OBDMID F0" => { command => "06 F0", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2104             "Vehicle manufacturer defined OBDMID F1" => { command => "06 F1", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2105             "Vehicle manufacturer defined OBDMID F2" => { command => "06 F2", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2106             "Vehicle manufacturer defined OBDMID F3" => { command => "06 F3", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2107             "Vehicle manufacturer defined OBDMID F4" => { command => "06 F4", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2108             "Vehicle manufacturer defined OBDMID F5" => { command => "06 F5", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2109             "Vehicle manufacturer defined OBDMID F6" => { command => "06 F6", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2110             "Vehicle manufacturer defined OBDMID F7" => { command => "06 F7", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2111             "Vehicle manufacturer defined OBDMID F8" => { command => "06 F8", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2112             "Vehicle manufacturer defined OBDMID F9" => { command => "06 F9", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2113             "Vehicle manufacturer defined OBDMID FA" => { command => "06 FA", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2114             "Vehicle manufacturer defined OBDMID FB" => { command => "06 FB", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2115             "Vehicle manufacturer defined OBDMID FC" => { command => "06 FC", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2116             "Vehicle manufacturer defined OBDMID FD" => { command => "06 FD", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2117             "Vehicle manufacturer defined OBDMID FE" => { command => "06 FE", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2118             "Vehicle manufacturer defined OBDMID FF" => { command => "06 FF", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2119            
2120            
2121             "Emission-related diagnostic trouble codes detected during current or last completed driving cycle" => { command => "07", available => 1,
2122             result => [
2123             {name => "DTC#1", type => "word_0", modifier => "+0", unit => ""},
2124             {name => "DTC#2", type => "word_1", modifier => "+0", unit => ""},
2125             {name => "DTC#3", type => "word_2", modifier => "+0", unit => ""},
2126             ] },
2127            
2128            
2129             "09 PIDs supported (01-20)" => { command => "09 00", available => 1,
2130             result => [
2131             {name => "MessageCount VIN", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
2132             {name => "Vehicle Identification Number", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
2133             {name => "MessageCount CALID", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
2134             {name => "Calibration Identifications", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
2135             {name => "MessageCount CVN", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
2136             {name => "Calibration Verification Numbers", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
2137             {name => "MessageCount IPT", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
2138             {name => "In-use Performance Tracking", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
2139            
2140             {name => "MessageCount ECUNAME", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
2141             {name => "ECUNAME", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
2142             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
2143             # {name => "", type => "bool_1", modifier => "&16", unit => ""},
2144             # {name => "", type => "bool_1", modifier => "&8", unit => ""},
2145             # {name => "", type => "bool_1", modifier => "&4", unit => ""},
2146             # {name => "", type => "bool_1", modifier => "&2", unit => ""},
2147             # {name => "", type => "bool_1", modifier => "&1", unit => ""},
2148            
2149             # {name => "", type => "bool_2", modifier => "&128", unit => ""},
2150             # {name => "", type => "bool_2", modifier => "&64", unit => ""},
2151             # {name => "", type => "bool_2", modifier => "&32", unit => ""},
2152             # {name => "", type => "bool_2", modifier => "&16", unit => ""},
2153             # {name => "", type => "bool_2", modifier => "&8", unit => ""},
2154             # {name => "", type => "bool_2", modifier => "&4", unit => ""},
2155             # {name => "", type => "bool_2", modifier => "&2", unit => ""},
2156             # {name => "", type => "bool_2", modifier => "&1", unit => ""},
2157            
2158             # {name => "", type => "bool_3", modifier => "&128", unit => ""},
2159             # {name => "", type => "bool_3", modifier => "&64", unit => ""},
2160             # {name => "", type => "bool_3", modifier => "&32", unit => ""},
2161             # {name => "", type => "bool_3", modifier => "&16", unit => ""},
2162             # {name => "", type => "bool_3", modifier => "&8", unit => ""},
2163             # {name => "", type => "bool_3", modifier => "&4", unit => ""},
2164             # {name => "", type => "bool_3", modifier => "&2", unit => ""},
2165             # {name => "09 PIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
2166             ] },
2167            
2168             "MessageCount VIN" => { command => "09 01", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2169             "Vehicle Identification Number" => { command => "09 02", result => [{type => "string_1", modifier => "", unit => ""}] },
2170             "MessageCount CALID" => { command => "09 03", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2171             "Calibration Identifications" => { command => "09 04", result => [{type => "string_1", modifier => "", unit => ""}] },
2172             "MessageCount CVN" => { command => "09 05", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2173             "Calibration Verification Numbers" => { command => "09 06", result => [{type => "dword_0", modifier => "+0", unit => ""}] },
2174             "MessageCount IPT" => { command => "09 07", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2175             "In-use Performance Tracking" => { command => "09 08",
2176             result => [
2177             {name => "OBD Monitoring Conditions Encountered Counts", type => "word_0", modifier => "+0", unit => ""},
2178             {name => "Ignition Counter", type => "word_1", modifier => "+0", unit => ""},
2179             {name => "Catalyst Monitor Completion Counts Bank 1", type => "word_2", modifier => "+0", unit => ""},
2180             {name => "Catalyst Monitor Conditions Encountered Counts Bank 1", type => "word_3", modifier => "+0", unit => ""},
2181             {name => "Catalyst Monitor Completion Counts Bank 2", type => "word_4", modifier => "+0", unit => ""},
2182             {name => "Catalyst Monitor Conditions Encountered Counts Bank 2", type => "word_5", modifier => "+0", unit => ""},
2183             {name => "O2 Sensor Monitor Completion Counts Bank 1", type => "word_6", modifier => "+0", unit => ""},
2184             {name => "O2 Sensor Monitor Conditions Encountered Counts Bank 1", type => "word_7", modifier => "+0", unit => ""},
2185             {name => "O2 Sensor Monitor Completion Counts Bank 2", type => "word_8", modifier => "+0", unit => ""},
2186             {name => "O2 Sensor Monitor Conditions Encountered Counts Bank 2", type => "word_9", modifier => "+0", unit => ""},
2187             {name => "EGR Monitor Completion Condition Counts", type => "word_10", modifier => "+0", unit => ""},
2188             {name => "EGR Monitor Conditions Encountered Counts", type => "word_11", modifier => "+0", unit => ""},
2189             {name => "AIR Monitor Completion Condition Counts (Secondary Air)", type => "word_12", modifier => "+0", unit => ""},
2190             {name => "AIR Monitor Conditions Encountered Counts (Secondary Air)", type => "word_13", modifier => "+0", unit => ""},
2191             {name => "EVAP Monitor Completion Condition Counts", type => "word_14", modifier => "+0", unit => ""},
2192             {name => "EVAP Monitor Conditions Encountered Counts", type => "word_15", modifier => "+0", unit => ""}
2193             ] },
2194             "MessageCount ECUNAME" => { command => "09 09", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2195             "ECUNAME" => { command => "09 0A", result => [{type => "string_0", modifier => "", unit => ""}] },
2196            
2197            
2198             "Permanent diagnostic trouble codes" => { command => "0A", available => 1,
2199             result => [
2200             {name => "DTC#1", type => "word_0", modifier => "+0", unit => ""},
2201             {name => "DTC#2", type => "word_1", modifier => "+0", unit => ""},
2202             {name => "DTC#3", type => "word_2", modifier => "+0", unit => ""},
2203             ] },
2204            
2205             };
2206            
2207            
2208 0 0         if (defined($replay_filename))
2209             {
2210 0           $self->Replay($replay_filename);
2211            
2212             # $self->ShowReadableValues();
2213             #print Dumper($self->{'get'});
2214             }
2215             else
2216             {
2217 0           $self->OpenPort($port_details);
2218 0           $self->ConfigureDevice();
2219 0           $self->FindAvailableCommands();
2220             }
2221            
2222 0           return $self;
2223             }
2224            
2225            
2226             #*****************************************************************
2227            
2228             =head2 PortOK
2229            
2230             Returns 1 if the serial port and ELM module are working or 0 if no ELM device could be connected to.
2231            
2232             $obd->PortOK();
2233             =cut
2234            
2235             sub PortOK
2236             {
2237 0     0 1   my ($self) = @_;
2238            
2239 0 0         if ($self->{'port'} == -1)
2240             {
2241 0 0         if ($self->{'debug_level'} > 0) { print "Serial port not initialised!\n"; }
  0            
2242 0           return 0;
2243             }
2244             else
2245             {
2246 0           return 1;
2247             }
2248             }
2249            
2250            
2251             #*****************************************************************
2252            
2253             =head2 ShowReadableValues
2254            
2255             Displays the list of values that can be read from the ELM/ECU.
2256            
2257             $obd->ShowReadableValues();
2258             =cut
2259            
2260             sub ShowReadableValues
2261             {
2262 0     0 1   my ($self) = @_;
2263            
2264 0           print "Values that the Read and Show functions can fetch from this vehicle:\n\n";
2265            
2266 0           while ( my ($parameter_name, $definition) = each %{$self->{'get'}} )
  0            
2267             {
2268 0 0 0       if (exists($definition->{'available'}) && $definition->{'available'} == 1)
2269             {
2270 0           print "Value: \"$parameter_name\"\n";
2271 0           print "Returns:\n";
2272 0           foreach my $result (@{$definition->{'result'}})
  0            
2273             {
2274 0 0         if (exists($result->{'name'}))
2275             {
2276 0           print "$result->{'name'}";
2277             }
2278             else
2279             {
2280 0           print "$parameter_name";
2281             }
2282 0 0 0       if (exists($result->{'unit'}) && $result->{'unit'} ne "")
    0          
2283             {
2284 0           print " ($result->{'unit'})";
2285             }
2286             elsif (substr($result->{'type'}, 0, 4) eq "bool")
2287             {
2288 0           print " (0 or 1)";
2289             }
2290 0           print "\n";
2291             }
2292 0           print "\n";
2293             }
2294             }
2295             }
2296            
2297            
2298             #*****************************************************************
2299            
2300             =head2 Show
2301            
2302             When passed the name of an OBD value (e.g. "Engine RPM") in $value_name,
2303             it displays the address of the ECU which returned the value, the name of
2304             the value which was read or the name of one of many parameters returned
2305             followed by the value and the name of any unit associated with the value.
2306            
2307             If an error occurred, a message will be displayed instead.
2308            
2309             $obd->Show($value_name);
2310            
2311             This function calls the 'Read' function.
2312             =cut
2313             sub Show
2314             {
2315 0     0 1   my ($self, $name, $parameter) = @_;
2316            
2317 0 0         if ($self->{'debug_level'} > 0) { print "~Show: $name\n"; }
  0            
2318            
2319 0           my $response = $self->Read($name, $parameter);
2320            
2321 0           print "$name:\n";
2322            
2323 0 0         if ($response->{'status'} eq "ok")
2324             {
2325 0           foreach my $result (@{$response->{'results'}})
  0            
2326             {
2327 0           print "$result->{'address'} - $result->{'name'}: $result->{'value'} $result->{'unit'}.";
2328 0 0         if (exists($result->{'min_limit'}))
2329             {
2330 0           print " Min: $result->{'min_limit'} $result->{'unit'}.";
2331             }
2332 0 0         if (exists($result->{'max_limit'}))
2333             {
2334 0           print " Max: $result->{'max_limit'} $result->{'unit'}.";
2335             }
2336 0           print "\n";
2337             }
2338             }
2339             else
2340             {
2341 0           print "$response->{'status_message'}\n";
2342             }
2343 0           print "\n";
2344            
2345 0           return $response;
2346             }
2347            
2348            
2349             #*****************************************************************
2350            
2351             =head2 Read
2352            
2353             When passed the name of an OBD value (e.g. "Engine RPM") in $value_name,
2354             it returns a reference to a structure containing a status flag and any
2355             responses:
2356            
2357             my $response = $obd->Read($value_name);
2358            
2359             if ($response->{'status'} eq "ok")
2360             {
2361             foreach my $result (@{$response->{'results'}})
2362             {
2363             print "$result->{'address'} - $result->{'name'}: $result->{'value'} $result->{'unit'}\n"
2364             }
2365             }
2366            
2367             In the example above, $result->{'address'} contains the address of the
2368             ECU which returned the value, $result->{'name'} contains the name of
2369             the value which was read or the name of one of many parameters returned.
2370             $result->{'value'} and $result->{'unit'} contain the value and the name
2371             of any unit associated with the value.
2372            
2373             Error conditions are indicated by a value of $response->{'status'} other
2374             than 'ok' and an expanded error message in $response->{'status_message'}
2375             (the default is 'No errors detected' when there is no error).
2376            
2377             Error Meaning
2378             ok No errors detected
2379             Zero length response No data was returned by the ECU
2380             NO DATA A 'NO DATA' response was returned by the ELM
2381             STOPPED A 'STOPPED' response was returned by the ELM
2382             Port not ok The connection to the ELM module failed
2383             Negative response The vehicle returned a negative response
2384             Unsupported name The vehicle does not support this value
2385             Unrecognised name ELM327.pm does not recognise this value
2386             =cut
2387            
2388             sub Read
2389             {
2390 0     0 1   my ($self, $name, $parameter) = @_;
2391            
2392 0           my $unit = "";
2393            
2394 0           my $results=();
2395            
2396 0           my $id;
2397             my $value;
2398            
2399 0 0         if ($self->{'debug_level'} > 0) { print "~Read: $name\n"; }
  0            
2400            
2401 0 0         if (exists($self->{'get'}->{$name}))
2402             {
2403 0 0 0       if (exists($self->{'get'}->{$name}->{'available'}) && $self->{'get'}->{$name}->{'available'} == 1)
2404             {
2405 0           my $command = $self->{'get'}->{$name}->{'command'};
2406            
2407 0 0 0       if (substr($name, 0, 12) eq "Freeze frame")
    0          
2408             {
2409 0 0         if (defined($parameter))
2410             {
2411 0           $command .= " ";
2412 0           $command .= sprintf("%02X", $parameter);
2413             }
2414             else
2415             {
2416 0           $command .= " 00"; # Default to freeze frame 0.
2417             }
2418             }
2419             elsif (substr($command, 0, 2) eq "05" && substr($command, 0, 5) ne "05 00")
2420             {
2421 0 0         if (defined($parameter))
2422             {
2423 0           $command .= " ";
2424 0           $command .= sprintf("%02X", $parameter);
2425             }
2426             else
2427             {
2428 0           $command .= " 01"; # Default to O2Sensor = Bank 1 - Sensor 1.
2429             }
2430             }
2431            
2432 0           $results->{'status'} = $self->Command($command);
2433            
2434 0 0         if ($results->{'status'} ne "ok")
2435             {
2436 0           $results->{'status_message'} = $self->{'status_meanings'}->{$results->{'status'}};
2437 0           return $results;
2438             }
2439            
2440 0 0 0       if (substr($command, 0, 2) eq "06" && substr($command, 0, 5) ne "06 00"
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
2441             && substr($command, 0, 5) ne "06 20" && substr($command, 0, 5) ne "06 40"
2442             && substr($command, 0, 5) ne "06 60" && substr($command, 0, 5) ne "06 80"
2443             && substr($command, 0, 5) ne "06 A0" && substr($command, 0, 5) ne "06 C0"
2444             && substr($command, 0, 5) ne "06 E0" && $self->{'bus_type'} eq "CAN") # Command 6 works differently from 1,2,5,9 etc.
2445             {
2446 0           $self->GetResultsCommand06_CAN(\$results);
2447             }
2448             else
2449             {
2450 0           foreach my $result (@{$self->{'get'}->{$name}->{'result'}})
  0            
2451             {
2452 0 0         if ($self->{'debug_level'} > 2) { print Dumper($result); }
  0            
2453 0 0         if (exists($result->{'name'}))
2454             {
2455 0           $id = $result->{'name'};
2456             }
2457             else
2458             {
2459 0           $id = $name;
2460             }
2461            
2462             # Parse the result type...
2463 0           my @type = split('_', , $result->{'type'});
2464            
2465 0           my $index = 0;
2466 0           my $sign = 0;
2467 0 0         if ($type[0] eq "signed")
2468             {
2469 0           $sign = 1;
2470 0           $index = 1;
2471             }
2472            
2473 0 0         if ($type[$index] eq "AT")
2474             {
2475 0           $value = ${$self->{'response'}}[0];
  0            
2476            
2477 0 0         if (defined($result->{'modifier'}))
2478             {
2479 0           my $statement = '$value' . $result->{'modifier'};
2480 0           eval( $statement ); # Allow the use of a regex if required
2481 0 0         if ($self->{'debug_level'} > 2) { print "Statement: $statement\n"; }
  0            
2482             }
2483            
2484 0 0         if ($self->{'debug_level'} > 1) { print "$id, $value$result->{'unit'}\n"; }
  0            
2485 0           push @{$results->{'results'}},{name => $id, value => $value, unit => $result->{'unit'}, address => "ELM327"};
  0            
2486             }
2487             else
2488             {
2489 0           $value = $self->GetResult($type[$index], $type[$index+1]);
2490 0 0         if ($self->{'debug_level'} > 2) { print "GetResult value: $value\n"; }
  0            
2491            
2492 0           my $iteration = 0;
2493 0           foreach $value (@{$self->{'command_results'}})
  0            
2494             {
2495 0 0         if ($self->{'debug_level'} > 2) { print "Raw value: $value\n"; }
  0            
2496            
2497 0 0         if ($value ne "no result")
2498             {
2499 0           $unit = $result->{'unit'};
2500            
2501 0 0 0       if ($type[$index] eq "byte" && $type[0] eq "signed")
    0 0        
2502             {
2503 0           my $byte_sign_mask = 128;
2504 0           my $byte_value_mask = 127;
2505            
2506 0           $value = ($value & $byte_value_mask) - ($value & $byte_sign_mask);
2507             }
2508             elsif ($type[$index] eq "word" && $type[0] eq "signed")
2509             {
2510 0           my $word_sign_mask = 32768;
2511 0           my $word_value_mask = 32767;
2512            
2513 0           $value = ($value & $word_value_mask) - ($value & $word_sign_mask);
2514             }
2515            
2516 0 0         if ($type[$index] ne "string")
2517             {
2518 0 0         if ($self->{'debug_level'} > 2) { print "$value $result->{'modifier'}\n"; }
  0            
2519 0           $value = eval( "$value $result->{'modifier'}" );
2520 0 0         if ($self->{'debug_level'} > 2) { print "$value\n"; }
  0            
2521            
2522             }
2523             else
2524             {
2525 0           my $statement = '$value' . $result->{'modifier'};
2526 0           eval( $statement ); # Allow the use of a regex if required
2527 0 0         if ($self->{'debug_level'} > 2) { print "Statement: $statement\n"; }
  0            
2528            
2529             }
2530            
2531 0 0         if ($type[$index] eq "bool")
2532             {
2533 0 0         if ($value != 0) { $value = 1; } # Other bits are masked out.
  0            
2534 0 0         if ($unit ne "")
2535             {
2536 0           my @meanings = split(',', $unit);
2537 0           $unit = "($meanings[$value])";
2538             }
2539             }
2540            
2541 0 0         if (exists($result->{'alternatives'}))
2542             {
2543 0           foreach my $alternative (@{$result->{'alternatives'}})
  0            
2544             {
2545 0 0         if ($alternative->{'value'} == $value)
2546             {
2547 0           $value = $alternative->{'meaning'};
2548 0           last;
2549             }
2550             }
2551             }
2552             }
2553            
2554            
2555 0 0         if ($self->{'debug_level'} > 2) { print "$id, $value $unit\n"; }
  0            
2556            
2557 0 0 0       if ($command eq "03" || $command eq "07" || $command eq "0A")
      0        
2558             {
2559 0           push @{$results->{'results'}},{name => $id, value_read => $value, value => $self->DecodeTroubleCode($value), unit => $unit, address => ${$self->{'command_addresses'}}[$iteration]};
  0            
  0            
2560             }
2561             else
2562             {
2563 0           push @{$results->{'results'}},{name => $id, value => $value, unit => $unit, address => ${$self->{'command_addresses'}}[$iteration]};
  0            
  0            
2564             }
2565 0           $iteration++;
2566             }
2567 0           $self->{'command_results'} = [];
2568             }
2569             }
2570             }
2571             }
2572             else
2573             {
2574 0 0         if ($self->{'debug_level'} > 2) { print "Unsupported name: $name\n"; }
  0            
2575 0           $results->{'status'} = "Unsupported name";
2576             }
2577             }
2578             else
2579             {
2580 0 0         if ($self->{'debug_level'} > 2) { print "Unrecognised name: $name\n"; }
  0            
2581 0           $results->{'status'} = "Unrecognised name";
2582             }
2583            
2584 0           $results->{'status_message'} = $self->{'status_meanings'}->{$results->{'status'}};
2585 0           return $results;
2586             }
2587            
2588            
2589             #*****************************************************************
2590            
2591             =head2 ShowTroubleCodes
2592            
2593             Display any trouble codes on the console:
2594            
2595             $obd->ShowTroubleCodes();
2596             =cut
2597            
2598             sub ShowTroubleCodes
2599             {
2600 0     0 1   my ($self) = @_;
2601            
2602 0           my $malfunction_indicator_lamp_mask = 128;
2603 0           my $number_of_codes_mask = 127;
2604            
2605 0 0         if ($self->{'debug_level'} > 0) { print "ShowTroubleCodes\n"; }
  0            
2606            
2607 0           $self->Command("01 01"); # Get number of trouble codes
2608            
2609 0           my $number_of_codes = $self->GetResult("byte");
2610            
2611 0           my $malfunction_indicator_lamp_state = $number_of_codes & $malfunction_indicator_lamp_mask;
2612 0           $number_of_codes &= $number_of_codes_mask;
2613            
2614 0           print "Malfunction indicator lamp state: ";
2615 0 0         if ($malfunction_indicator_lamp_state > 0)
2616             {
2617 0           print "ON\n";
2618             }
2619             else
2620             {
2621 0           print "OFF\n";
2622             }
2623            
2624 0 0 0       if ($number_of_codes > 0 || $malfunction_indicator_lamp_state > 0)
2625             {
2626 0           print "$number_of_codes trouble code";
2627 0 0         if ($number_of_codes != 1) { print "s"; }
  0            
2628 0           print ":\n";
2629            
2630 0           $self->Show("Emission-related diagnostic trouble codes");
2631 0           $self->Show("Emission-related diagnostic trouble codes detected during current or last completed driving cycle");
2632             }
2633             else
2634             {
2635 0           print "No trouble codes found.\n";
2636             }
2637             }
2638            
2639            
2640             #*****************************************************************
2641            
2642             =head2 ClearTroubleCodes
2643            
2644             Clear any Trouble Codes and sensor data:
2645            
2646             $obd->ClearTroubleCodes();
2647            
2648             Note that clearing the sensor data will cause the vehicle to run on
2649             default values until it has recalibrated itself. This may affect
2650             performance and fuel economy.
2651            
2652             The ISO specification also insists that any user interface which
2653             invokes this function should display an "are you sure?" message
2654             to the user before calling it.
2655            
2656             =cut
2657            
2658             sub ClearTroubleCodes
2659             {
2660 0     0 1   my ($self) = @_;
2661            
2662 0 0         if ($self->{'debug_level'} > 0) { print "~ClearTroubleCodes\n"; }
  0            
2663 0           $self->Command("04"); # Clear Trouble Codes and sensor data
2664            
2665 0           my $result = $self->GetResult("byte");
2666            
2667 0           return $result; # Returns 0 if codes have been cleared or error code.
2668             }
2669            
2670            
2671             #*****************************************************************
2672            
2673             =head2 DecodeTroubleCode
2674            
2675             Expand a trouble code (e.g. 4216) to the full ISO code (C0216)
2676            
2677             This function is called by 'Read'.
2678            
2679             $decoded_code = $obd->DecodeTroubleCode($code);
2680             =cut
2681            
2682             sub DecodeTroubleCode
2683             {
2684 0     0 1   my ($self, $code) = @_;
2685            
2686 0           my @codes = ("P0","P1","P2","P3","C0","C1","C2","C3","B0","B1","B2","B3","U0","U1","U2","U3");
2687            
2688 0           my $code_prefix_mask = 61440;
2689 0           my $code_mask = 4095;
2690 0           my $number_of_codes_mask = 127;
2691            
2692 0 0 0       if ($code eq "no result" || $code == 0)
2693             {
2694 0           return "No Trouble Code";
2695             }
2696            
2697 0           my $code_prefix = ($code & $code_prefix_mask) >> 12;
2698 0           $code &= $code_mask;
2699 0           $code = sprintf("%03X", $code);
2700 0           my $decoded_code = "$codes[$code_prefix]$code";
2701            
2702 0 0         if ($self->{'debug_level'} > 1)
2703             {
2704 0           print "Code prefix: $code_prefix, Code: $code, Decoded: $decoded_code\n";
2705             }
2706 0           return $decoded_code;
2707             }
2708            
2709            
2710             #*****************************************************************
2711            
2712             =head2 CalibrateVoltage
2713            
2714             Changes the calibration value used by the ELM module. The value
2715             $Voltage is a string containing a fixed point value of the form:
2716             xx.xx, e.g "11.99", "12.01" etc.
2717            
2718             $obd->CalibrateVoltage($Voltage);
2719            
2720             The Voltage can be read by calling:
2721            
2722             my $response = $obd->read("Input Voltage");
2723            
2724             =cut
2725            
2726             sub CalibrateVoltage
2727             {
2728 0     0 1   my ($self, $Voltage) = @_;
2729            
2730 0 0         if ($self->{'debug_level'} > 0) { print "~CalibrateVoltage: $Voltage\n"; }
  0            
2731            
2732 0           $self->Command("AT CV $Voltage"); # Calibrate Voltage
2733 0           return ${$self->{'response'}}[0];
  0            
2734             }
2735            
2736            
2737             #*****************************************************************
2738            
2739             =head2 ResetVoltage
2740            
2741             Resets the ELM module's Voltage calibration to the factory setting:
2742            
2743             $obd->ResetVoltage();
2744             =cut
2745            
2746             sub ResetVoltage
2747             {
2748 0     0 1   my ($self) = @_;
2749            
2750 0 0         if ($self->{'debug_level'} > 0) { print "~ResetVoltage:\n"; }
  0            
2751            
2752 0           $self->Command("AT CV 0000"); # Reset Voltage to factory setting
2753 0           return ${$self->{'response'}}[0];
  0            
2754             }
2755            
2756            
2757             #*****************************************************************
2758            
2759             =head2 WriteStoredDataByte
2760            
2761             Writes $byte_value to the ELM module's non-volatile storage area.
2762            
2763             $obd->WriteStoredDataByte($byte_value);
2764            
2765             The value of this byte can be read using:
2766            
2767             $obd->Read("Stored data byte");
2768            
2769             =cut
2770            
2771             sub WriteStoredDataByte
2772             {
2773 0     0 1   my ($self, $value) = @_;
2774            
2775 0 0         if ($self->{'debug_level'} > 0) { print "~WriteStoredDataByte: $value\n"; }
  0            
2776            
2777 0           $self->Command("AT SD $value"); # Save Data byte value
2778 0           return ${$self->{'response'}}[0];
  0            
2779             }
2780            
2781            
2782             #*****************************************************************
2783            
2784             =head2 Command
2785            
2786             Send a command to the ELM, read any response and decode it if
2787             was an ECU command.
2788             AT command responses are placed in the $self->{'response'} array.
2789             Responses to ECU commands are written to the $self->{'results'}
2790             structure. On return a status of 0 indicates no errors.
2791            
2792             This function is called by other module functions 'Read',
2793             'ClearTroubleCodes' etc., but can be used to send commands that aren't
2794             otherwise supported.
2795            
2796             $status = $obd->Command($command_string);
2797             =cut
2798            
2799             sub Command
2800             {
2801 0     0 1   my ($self, $command) = @_;
2802            
2803 0           my $status = "ok";
2804            
2805 0 0         if ($self->{'debug_level'} > 0) { print "~Command: $command\n"; }
  0            
2806 0           my @command_parts = split(' ', $command);
2807            
2808 0           $status = $self->WriteCommand("$command");
2809            
2810             do
2811 0           {
2812 0           $status = $self->ReadResponse();
2813            
2814 0 0 0       if ($command_parts[0] ne "AT" && $status eq "ok")
2815             {
2816 0           $self->{'last_command'} = hex($command_parts[0]);
2817 0 0         if ($has_sub_command[$self->{'last_command'}])
2818             {
2819 0           $self->{'last_sub_command'} = hex($command_parts[1]);
2820             }
2821             else
2822             {
2823 0           $self->{'last_sub_command'} = 0;
2824             }
2825            
2826 0           $status = $self->DecodeResponse();
2827             }
2828            
2829             } while ($status eq "Request Correctly Received - Response Pending");
2830            
2831 0           return $status;
2832             }
2833            
2834            
2835             #*****************************************************************
2836            
2837             =head2 GetResult
2838            
2839             Returns a value from the last set of results from the ELM/ECU
2840            
2841             $type can be one of the following:
2842             bool (1 bit), byte (8 bit), word (16 bit), dword (32 bit) or string.
2843             $number is the zero-based index into the array of results and takes
2844             the type into account such that $number=0 returns the first byte,
2845             word or dword and $number=1, returns the second.
2846             Booleans are treated the same as bytes and require individual bits
2847             to be extracted separately.
2848             For strings, $number is the offset of the start of the string.
2849            
2850             This function is called by 'Read'.
2851            
2852             $obd->GetResult($type, $number);
2853             =cut
2854            
2855             sub GetResult
2856             {
2857 0     0 1   my ($self, $type, $number) = @_;
2858            
2859 0           my $result;
2860 0           $self->{'number_of_results'} = 0;
2861            
2862 0 0         if (!defined($number)) { $number = 0; }
  0            
2863            
2864 0 0         if ($self->{'debug_level'} > 1) { print "GetResult: Type: $type: Number: $number\n"; }
  0            
2865            
2866 0           foreach my $address (sort keys %{$self->{'results'}})
  0            
2867             {
2868 0           my $number_of_result_bytes = $self->{'results'}->{$address}->{'response_length'};
2869 0 0 0       if ($self->{'results'}->{$address}->{'command'} == $self->{'last_command'} &&
2870             $self->{'results'}->{$address}->{'sub_command'} == $self->{'last_sub_command'})
2871             {
2872 0 0         if ($type eq "bool")
    0          
    0          
    0          
    0          
2873             {
2874 0 0         if ($number_of_result_bytes < ($number+1))
2875             {
2876 0           $result = "no result";
2877             }
2878             else
2879             {
2880 0           $result = ${$self->{'results'}->{$address}->{'result'}}[$number];
  0            
2881             }
2882 0           push @{$self->{'command_addresses'}}, $address;
  0            
2883 0           push @{$self->{'command_results'}}, $result;
  0            
2884 0           $self->{'number_of_results'}++;
2885             }
2886             elsif ($type eq "byte")
2887             {
2888 0 0         if ($number_of_result_bytes < ($number+1))
2889             {
2890 0           $result = "no result";
2891             }
2892             else
2893             {
2894 0           $result = ${$self->{'results'}->{$address}->{'result'}}[$number];
  0            
2895             }
2896 0           push @{$self->{'command_addresses'}}, $address;
  0            
2897 0           push @{$self->{'command_results'}}, $result;
  0            
2898 0           $self->{'number_of_results'}++;
2899             }
2900             elsif ($type eq "word")
2901             {
2902 0 0         if ($number_of_result_bytes < (($number*2)+2))
2903             {
2904 0 0         if ($self->{'debug_level'} > 2) { print "Number of result bytes: $number_of_result_bytes\n"; }
  0            
2905 0           $result = "no result";
2906             }
2907             else
2908             {
2909 0           $result = ((${$self->{'results'}->{$address}->{'result'}}[$number*2] * 256) + ${$self->{'results'}->{$address}->{'result'}}[($number*2)+1] );
  0            
  0            
2910             }
2911 0           push @{$self->{'command_addresses'}}, $address;
  0            
2912 0           push @{$self->{'command_results'}}, $result;
  0            
2913 0           $self->{'number_of_results'}++;
2914             }
2915             elsif ($type eq "dword")
2916             {
2917 0 0         if ($number_of_result_bytes < (($number*4)+4))
2918             {
2919 0           $result = "no result";
2920             }
2921             else
2922             {
2923 0           $result = ((${$self->{'results'}->{$address}->{'result'}}[$number*4] * 16777216) + ${$self->{'results'}->{$address}->{'result'}}[($number*4)+1] * 65536);
  0            
  0            
2924 0           $result += ((${$self->{'results'}->{$address}->{'result'}}[($number*4)+2] * 256) + ${$self->{'results'}->{$address}->{'result'}}[($number*4)+3] );
  0            
  0            
2925             }
2926 0           push @{$self->{'command_addresses'}}, $address;
  0            
2927 0           push @{$self->{'command_results'}}, $result;
  0            
2928 0           $self->{'number_of_results'}++;
2929             }
2930             elsif ($type eq "string")
2931             {
2932 0 0         if ($number_of_result_bytes < $number)
2933             {
2934 0           $result = "no result";
2935             }
2936             else
2937             {
2938 0           $result = "";
2939 0           foreach (@{$self->{'results'}->{$address}->{'result'}})
  0            
2940             {
2941 0 0         if ($number > 0)
2942             {
2943 0           $number--;
2944             }
2945             else
2946             {
2947 0 0 0       if ($_ > 32 && $_ < 127) # Ignore non-printable characters
2948             {
2949 0           $result .= chr($_);
2950             }
2951             }
2952             }
2953             }
2954 0           push @{$self->{'command_addresses'}}, $address;
  0            
2955 0           push @{$self->{'command_results'}}, $result;
  0            
2956 0           $self->{'number_of_results'}++;
2957             }
2958             }
2959             else
2960             {
2961 0           $result = 0;
2962             }
2963             }
2964            
2965 0           return $result;
2966             }
2967            
2968            
2969             #*****************************************************************
2970            
2971            
2972             =head2 WriteCommand
2973            
2974             Write a command to the serial port unless replay is in progress.
2975            
2976             This function is called by the 'Command' function.
2977            
2978             $status = $obd->WriteCommand($command_string);
2979             =cut
2980            
2981             sub WriteCommand
2982             {
2983 0     0 1   my ($self, $command) = @_;
2984            
2985 0           my $status = "ok";
2986            
2987 0 0         if ($self->{'debug_level'} > 0) { print "~WriteCommand: $command\n"; }
  0            
2988            
2989 0 0         if ($self->{'replay_file'} == 0)
2990             {
2991 0 0         if ($self->PortOK)
2992             {
2993 0           $command .= "$cr$lf";
2994 0           $self->{'port'}->write("$command");
2995             }
2996             else
2997             {
2998 0           $status = "Port not ok";
2999             }
3000             }
3001            
3002 0           return $status;
3003             }
3004            
3005             #*****************************************************************
3006            
3007             =head2 ReadResponse
3008            
3009             Read the ELM's response from the serial port and put each line
3010             into the $self->{'response'} array.
3011             Turn on debugging for a dump of the response array.
3012            
3013             This function is called by the 'Command' function.
3014            
3015             $status = $obd->ReadResponse();
3016             =cut
3017            
3018             sub ReadResponse
3019             {
3020 0     0 1   my ($self) = @_;
3021            
3022 0           my $bytes_to_read = 1;
3023 0           my $count_in = 0;
3024 0           my $string_in = "";
3025 0           my $status = "ok";
3026             # my $timeout = 4; # Command 01 04 failed when timeout was 2
3027            
3028             # Retry failed (empty) reads this many times with increasingly longer
3029             # delays between each read. Hopefully this will allow us to recover
3030             # quickly when possible but still give the ECU time to respond.
3031 0           my $tries = $self->{'rr_tries'};
3032 0           my $try_delay = $self->{'rr_retry_delay'};
3033            
3034 0           my $line = "";
3035 0           $self->{'response'} = (); # Array of strings, one per line of the response.
3036 0           $self->{'response_length'} = 0;
3037            
3038 0 0         if ($self->{'debug_level'} > 1) { print "ReadResponse\n"; }
  0            
3039            
3040 0 0 0       if ($self->{'replay_file'} == 0 && $self->PortOK)
3041             {
3042 0           my $try = 0;
3043 0           my $prev = '';
3044             do
3045 0   0       {
3046 0           ($count_in, $string_in) = $self->{'port'}->read($bytes_to_read);
3047             # if ($count_in == $bytes_to_read && $string_in ne $null)
3048             # {
3049             # $line .= $string_in;
3050             # $self->{'response_length'}++;
3051             # }
3052             # else
3053             # {
3054             # sleep 1;
3055             # $timeout--;
3056             # }
3057             # } while ($count_in == 0 && $timeout>0);
3058             #
3059             # do
3060             # {
3061             # ($count_in, $string_in) = $self->{'port'}->read($bytes_to_read);
3062 0 0         print "count_in=$count_in, string_in=$string_in\n"
3063             if $self->{debug_level} > 5;
3064            
3065 0 0 0       if ($count_in == $bytes_to_read)
    0          
3066             {
3067             # Reset our try counter each time we successfully read
3068 0           $try = 0;
3069            
3070 0 0 0       if ($string_in ne ">" && $string_in ne $null)
3071             {
3072 0 0         if ($string_in eq $cr)
    0          
3073             {
3074 0 0         if ($line ne "")
3075             {
3076 0 0         print "Adding Line: |$line| = ".length($line)."\n"
3077             if $self->{debug_level} > 5;
3078 0           push @{$self->{'response'}}, $line;
  0            
3079 0           $line = "";
3080             }
3081             }
3082             # else
3083             elsif (index ("\r\n", $string_in) == -1 )
3084             {
3085 0           $line .= $string_in;
3086 0           $self->{'response_length'}++;
3087             }
3088             }
3089 0           $prev = $string_in;
3090             }
3091             elsif ($prev eq '>' && !length($line))
3092             {
3093             # '>' on a line by itself signals the end of the response
3094 0           $try = $tries+1;
3095             }
3096             else
3097             {
3098             # Failed read, try again (immediatly if this is our first retry ($try == 0))
3099 0 0 0       print "sleeping ".($try_delay * $try)." [$try of $tries]\n"
3100             if $try && $self->{debug_level} > 5;
3101 0 0         sleep ($try_delay * $try) if $try_delay * $try > 0;
3102 0           $try++;
3103             }
3104             # } while ($count_in == $bytes_to_read);
3105             } while ($count_in == $bytes_to_read || $try <= $tries);
3106             }
3107             else
3108             {
3109             # Load in the lines of the response from the replay file
3110 0           while (scalar(@{$self->{'replay_response'}}) > 0)
  0            
3111             {
3112 0           $line = shift @{$self->{'replay_response'}};
  0            
3113 0           push @{$self->{'response'}}, $line;
  0            
3114 0           $self->{'response_length'} += length($line);
3115             }
3116             }
3117            
3118 0 0         if ($self->{'response_length'} == 0)
    0          
    0          
3119             {
3120 0           $status = "Zero length response";
3121             }
3122             elsif ($self->{'response'}[0] eq "NO DATA")
3123             {
3124 0           $status = "NO DATA";
3125             }
3126             elsif ($self->{'response'}[0] eq "STOPPED")
3127             {
3128 0           $status = "STOPPED";
3129             }
3130            
3131 0 0         if ($self->{'debug_level'} > 0)
3132             {
3133 0           print "Response\n";
3134 0           foreach (@{$self->{'response'}})
  0            
3135             {
3136 0           print "$_\n";
3137             }
3138 0           print "End of response\n";
3139             }
3140            
3141 0           return $status;
3142             }
3143            
3144            
3145             #*****************************************************************
3146            
3147             =head2 DecodeResponse
3148            
3149             Decode the ECU response (in the $self->{'response'} array) and
3150             write the result to the $self->{'results'} structure.
3151            
3152             This function is called by the 'Command' function.
3153            
3154             $status = $obd->DecodeResponse();
3155             =cut
3156            
3157             sub DecodeResponse
3158             {
3159 0     0 1   my ($self) = @_;
3160            
3161 0           my $status = "ok";
3162 0           my $results = {};
3163 0           my $command_mask = 63;
3164 0           my $line_number = 0;
3165 0           my $result_string;
3166            
3167 0           $self->{'command_addresses'} = [];
3168 0           $self->{'command_results'} = [];
3169 0           $self->{'number_of_results'} = 0;
3170            
3171 0 0         if ($self->{'debug_level'} > 1)
3172             {
3173 0           print "\nDecodeResponse\n";
3174 0           print "Lines: ".scalar(@{$self->{'response'}})."\n";
  0            
3175             }
3176            
3177 0           for (keys %{$self->{'results'}})
  0            
3178             {
3179 0           delete $self->{'results'}->{$_};
3180             }
3181            
3182 0           foreach (@{$self->{'response'}})
  0            
3183             {
3184 0           my @line_parts = split(' ', $_);
3185 0 0         if (scalar(@line_parts) > 2)
3186             {
3187 0           my $address = shift @line_parts;
3188 0 0         if (length($address) < 3)
3189             {
3190             # Not CAN ($address contains the priority byte)
3191 0 0         if ($self->{'debug_level'} > 4) { print "Response type: SAE J1979\n"; }
  0            
3192 0           $line_number++;
3193 0           my $recipient_address = shift @line_parts;
3194 0           $address = shift @line_parts; # Transmitter address
3195 0           $self->{'results'}->{$address}->{'response_code'} = 0;
3196 0           $self->{'results'}->{$address}->{'format'} = "Other";
3197 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts) & $command_mask);
3198 0 0         if ($self->{'results'}->{$address}->{'command'} == 4) { push(@line_parts, "00"); }
  0            
3199 0 0         if ($self->{'results'}->{$address}->{'command'} == $command_mask)
3200             {
3201 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts));
3202             }
3203 0 0         if ($has_sub_command[$self->{'results'}->{$address}->{'command'}])
3204             {
3205 0           $self->{'results'}->{$address}->{'sub_command'} = hex(shift @line_parts);
3206             }
3207             else
3208             {
3209 0           $self->{'results'}->{$address}->{'sub_command'} = 0;
3210             }
3211 0 0         if ($self->{'results'}->{$address}->{'command'} == 2)
    0          
    0          
3212             {
3213 0           $self->{'results'}->{$address}->{'frame'} = hex(shift @line_parts);
3214             }
3215             elsif ($self->{'results'}->{$address}->{'command'} == 5)
3216             {
3217 0           $self->{'results'}->{$address}->{'O2sensor'} = hex(shift @line_parts);
3218             }
3219             elsif ($self->{'results'}->{$address}->{'command'} == 6)
3220             {
3221 0           $self->{'results'}->{$address}->{'Limit_type_and_component_id'} = hex(shift @line_parts);
3222             }
3223 0 0         if (exists($self->{'results'}->{$address}->{'response_length'}))
3224             {
3225 0           $self->{'results'}->{$address}->{'response_length'} += hex(scalar(@line_parts));
3226             }
3227             else
3228             {
3229 0           $self->{'results'}->{$address}->{'response_length'} = hex(scalar(@line_parts));
3230             }
3231             }
3232             else
3233             {
3234             # CAN
3235 0 0         if ($self->{'debug_level'} > 4) { print "Response type: CAN\n"; }
  0            
3236 0           $self->{'results'}->{$address}->{'response_code'} = 0;
3237 0           $self->{'results'}->{$address}->{'format'} = "CAN";
3238 0           $line_number = hex(shift @line_parts);
3239            
3240 0 0         if ($line_number <= 16)
3241             {
3242 0 0         if ($line_number == 16)
3243             {
3244 0           $self->{'results'}->{$address}->{'response_length'} = hex(shift @line_parts);
3245             }
3246            
3247 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts) & $command_mask); # Error code will now be 63 rather than 7F
3248            
3249 0 0         if ($line_number < 16)
3250             {
3251 0 0 0       if ($has_sub_command[$self->{'results'}->{$address}->{'command'}] || $self->{'results'}->{$address}->{'command'} == $command_mask)
3252             {
3253 0           $self->{'results'}->{$address}->{'response_length'} = $line_number - 2; # Do not include command and sub-command bytes
3254             }
3255             else
3256             {
3257 0           $self->{'results'}->{$address}->{'response_length'} = $line_number - 1; # Do not include command byte (no sub-command byte)
3258             }
3259             }
3260            
3261 0 0         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.
  0            
3262            
3263 0 0         if ($self->{'results'}->{$address}->{'command'} == $command_mask) # If there was an error, shift out the real command number.
3264             {
3265 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts));
3266 0           $self->{'results'}->{$address}->{'response_code'} = $line_parts[0];
3267             }
3268             else
3269             {
3270 0 0         if ($has_sub_command[$self->{'results'}->{$address}->{'command'}])
3271             {
3272 0           $self->{'results'}->{$address}->{'sub_command'} = hex(shift @line_parts);
3273             }
3274             else
3275             {
3276 0           $self->{'results'}->{$address}->{'sub_command'} = 0;
3277             }
3278 0 0         if ($self->{'results'}->{$address}->{'command'} == 2)
3279             {
3280 0           $self->{'results'}->{$address}->{'frame'} = hex(shift @line_parts);
3281             }
3282             }
3283             }
3284             }
3285 0           $self->{'bus_type'} = $self->{'results'}->{$address}->{'format'};
3286 0           $results->{$address}->{$line_number} = join(" ", @line_parts);
3287 0           $self->{'results'}->{$address}->{'response_reason'} = $self->{'negative_response_codes'}->{$self->{'results'}->{$address}->{'response_code'}};
3288 0           $status = $self->{'results'}->{$address}->{'response_reason'};
3289             }
3290             }
3291            
3292 0 0         if ($self->{'debug_level'} > 2)
3293             {
3294 0           print "Decoded results:\n";
3295 0           print Dumper($results);
3296             }
3297            
3298 0           foreach my $address (sort keys %{$results})
  0            
3299             {
3300 0           $result_string = "";
3301 0           foreach my $line (sort keys %{$results->{$address}})
  0            
3302             {
3303 0           $result_string .= "$results->{$address}->{$line} ";
3304             }
3305 0           @{$self->{'results'}->{$address}->{'result'}} = split(' ', $result_string);
  0            
3306            
3307            
3308             #Now turn the hex byte strings into numbers...
3309 0           foreach (@{$self->{'results'}->{$address}->{'result'}})
  0            
3310             {
3311 0           $_ = hex($_);
3312             }
3313             }
3314            
3315 0 0         if ($self->{'debug_level'} > 1)
3316             {
3317 0           print "\nFully decoded results:\n";
3318 0           print Dumper($self->{'results'});
3319             }
3320            
3321 0           return $status;
3322             }
3323            
3324            
3325             #*****************************************************************
3326            
3327             =head2 GetResultsCommand06_CAN
3328            
3329             Get the results for command 06 on a CAN system.
3330            
3331             This function is called by 'Read' and is not intended to be called by
3332             other functions.
3333            
3334             $obd->GetResultsCommand06_CAN($results_reference);
3335             =cut
3336            
3337             sub GetResultsCommand06_CAN
3338             {
3339 0     0 1   my ($self, $results_ref) = @_;
3340            
3341 0           my $results = $$results_ref;
3342            
3343 0           foreach my $address (sort keys %{$self->{'results'}})
  0            
3344             {
3345 0           my $index = 0;#1;
3346 0           my $number_of_header_bytes = 2; # Allow for TID and OBDMIDID
3347 0           my $number_of_result_bytes = $self->{'results'}->{$address}->{'response_length'} - $number_of_header_bytes;
3348             do
3349 0           {
3350 0 0         if ($index != 0)
3351             {
3352 0           $index++; # Skip over OBDMIDID in subsequent records.
3353             }
3354             # my $obdmid_id = ${$self->{'results'}->{$address}->{'result'}}[$index];
3355 0           my $sdt_id = ${$self->{'results'}->{$address}->{'result'}}[$index];
  0            
3356 0           my $uas_id = ${$self->{'results'}->{$address}->{'result'}}[$index+1];
  0            
3357            
3358 0           my $test_value = ${$self->{'results'}->{$address}->{'result'}}[$index+2] * 256;
  0            
3359 0           $test_value += ${$self->{'results'}->{$address}->{'result'}}[$index+3];
  0            
3360            
3361 0           my $min_test_limit = ${$self->{'results'}->{$address}->{'result'}}[$index+4] * 256;
  0            
3362 0           $min_test_limit += ${$self->{'results'}->{$address}->{'result'}}[$index+5];
  0            
3363            
3364 0           my $max_test_limit = ${$self->{'results'}->{$address}->{'result'}}[$index+6] * 256;
  0            
3365 0           $max_test_limit += ${$self->{'results'}->{$address}->{'result'}}[$index+7];
  0            
3366            
3367 0           my $test_name = "Unrecognised test Id ($sdt_id)";
3368            
3369 0 0         if (exists($self->{'Standardized_Test_IDs'}->{$sdt_id}))
3370             {
3371 0           $test_name = $self->{'Standardized_Test_IDs'}->{$sdt_id}->{'name'};
3372             }
3373            
3374 0           my $unit = "unknown";
3375            
3376 0 0         if ($uas_id >= 128)
3377             {
3378 0           my $word_sign_mask = 32768;
3379 0           my $word_value_mask = 32767;
3380            
3381 0           $test_value = ($test_value & $word_value_mask) - ($test_value & $word_sign_mask);
3382 0           $min_test_limit = ($min_test_limit & $word_value_mask) - ($min_test_limit & $word_sign_mask);
3383 0           $max_test_limit = ($max_test_limit & $word_value_mask) - ($max_test_limit & $word_sign_mask);
3384             }
3385            
3386 0 0         if (exists($self->{'unit_and_scaling_identifiers'}->{$uas_id}))
3387             {
3388 0           $unit = $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'unit'};
3389            
3390 0           $test_value = eval( "$test_value $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'modifier'}" );
3391 0           $min_test_limit = eval( "$min_test_limit $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'modifier'}" );
3392 0           $max_test_limit = eval( "$max_test_limit $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'modifier'}" );
3393             }
3394            
3395 0           push @{$results->{'results'}},{address => $address, name => $test_name, value => $test_value, max_limit => $max_test_limit, min_limit => $min_test_limit, unit => $unit};
  0            
3396            
3397 0           $index += 8;
3398             } while(($index+8) < $number_of_result_bytes);
3399             }
3400            
3401 0 0         if ($self->{'debug_level'} > 2)
3402             {
3403 0           print "Command 06 - results:\n";
3404 0           print Dumper($self->{'results'});
3405             }
3406             }
3407            
3408            
3409             #*****************************************************************
3410            
3411             =head2 OpenPort
3412            
3413             Try to find an ELM module on a COM port.
3414             If $port_details contains the name of a port, start with that one and
3415             work upwards.
3416            
3417             To override the default serial port settings (38400, no parity, 8 data
3418             bits, 1 stop bit, no handshaking), you can pass values in $port_details
3419             in the following format:
3420            
3421             port_name:baud_rate:parity:data_bits:stop_bits:handshake
3422            
3423             e.g.
3424            
3425             $port_details = "/dev/ttyUSB0:115200:none:8:1:none";
3426            
3427             The port name may be left out:
3428            
3429             $port_details = "115200:none:8:1:none";
3430            
3431             It is also ok to just define the port name and/or baud rate and use
3432             default values for parity, data bits, stop bits and handshake:
3433            
3434             $port_details = "/dev/ttyUSB0:115200";
3435             or
3436             $port_details = "115200";
3437            
3438             On Linux you may see the error:
3439             "Can't open /dev/ttyUSB0: Permission denied".
3440             This can be avoided by running as root or by adding your user to the
3441             'dialout' group.
3442            
3443            
3444             This function is called by 'new'.
3445            
3446             $obd->OpenPort($port_details);
3447             =cut
3448            
3449             sub OpenPort
3450             {
3451 0     0 1   my ($self, $port_details) = @_;
3452 0           my $quiet = 0;
3453 0           my $port = -1;
3454 0           my $port_count = 0;
3455 0           my $port_name = undef;
3456 0           my $baud_rate = 38400;
3457 0           my $parity = "none";
3458 0           my $data_bits = 8;
3459 0           my $stop_bits = 1;
3460 0           my $handshake = "none";
3461            
3462 0 0 0       if (defined($port_details) && $port_details ne "")
3463             {
3464 0           my @parameters= split(":", $port_details);
3465            
3466 0 0         if ($parameters[0] ne "")
3467             {
3468 0           my $parameter = $parameters[0];
3469 0           $parameter =~ s/[0-9]//g; # Strip everything that is numeric
3470 0 0         if ($parameter ne "") # If a valid serial port name has been passed
3471             {
3472 0           $port_name = shift @parameters;
3473             }
3474             }
3475 0 0         if (scalar(@parameters) > 0)
3476             {
3477 0           $baud_rate = shift @parameters;
3478 0 0         if (scalar(@parameters) > 0)
3479             {
3480 0           $parity = shift @parameters;
3481 0 0         if (scalar(@parameters) > 0)
3482             {
3483 0           $data_bits = shift @parameters;
3484 0 0         if (scalar(@parameters) > 0)
3485             {
3486 0           $stop_bits = shift @parameters;
3487 0 0         if (scalar(@parameters) > 0)
3488             {
3489 0           $handshake = shift @parameters;
3490             }
3491             }
3492             }
3493             }
3494             }
3495             }
3496            
3497 0 0 0       if (!defined($port_name) || $port_name eq "")
3498             {
3499 0 0         if ($^O eq "MSWin32")
3500             {
3501 0           $port_name = "COM1";
3502             }
3503             else
3504             {
3505 0           $port_name = "/dev/ttyUSB0";
3506             }
3507             }
3508            
3509 0           my $port_number = $port_name;
3510 0           $port_number =~ s/[^0-9]//g; # Strip everything that isn't numeric
3511            
3512 0           my $port_text = $port_name;
3513 0           $port_text =~ s/[0-9]//g; # Strip everything that is numeric
3514            
3515             do
3516 0   0       {
      0        
3517 0           $port_name = $port_text.$port_number;
3518            
3519 0 0         if ($^O eq "MSWin32")
3520             {
3521 0           $port = Win32::SerialPort->new ($port_name);
3522             }
3523             else
3524             {
3525 0           $port = Device::SerialPort->new($port_name, $quiet);
3526             }
3527            
3528 0 0         if (defined($port))
3529             {
3530 0           $port->user_msg(1); # misc. warnings
3531 0           $port->error_msg(1); # hardware and data errors
3532            
3533 0           $port->baudrate($baud_rate);
3534 0           $port->parity($parity);
3535 0 0         if ($parity eq "none")
3536             {
3537 0           $port->parity_enable(0);
3538             }
3539             else
3540             {
3541 0           $port->parity_enable(1); # for any parity except "none"
3542             }
3543 0           $port->databits($data_bits);
3544 0           $port->stopbits($stop_bits);
3545 0           $port->handshake($handshake);
3546            
3547 0           $port->write_settings;
3548            
3549 0           $self->{'port'} = $port;
3550 0           $self->Command("AT Z"); # Reset Device
3551 0           foreach (@{$self->{'response'}})
  0            
3552             {
3553 0 0         if (substr($_, 0, 5) eq "ELM32") # Allow 328 & 329 as well
3554             {
3555 0           $self->{'ELM_type'} = substr($_, 0, 6);
3556             }
3557             }
3558 0 0 0       if ($self->{'ELM_type'} eq "NONE" && $self->{'debug_level'} > 0)
3559             {
3560 0           print "Can't find an ELM module on $port_name\n";
3561             }
3562             }
3563             else
3564             {
3565 0 0         if ($self->{'debug_level'} > 0)
3566             {
3567 0           print "Can't open $port_name: $!\n";
3568             }
3569 0           $self->{'port'} = -1;
3570             }
3571            
3572 0           $port_number++;
3573 0           $port_count++;
3574             } until(($self->{'port'} != -1 && $self->{'ELM_type'} ne "NONE") || $port_count > $max_ports_to_search);
3575            
3576 0 0         if ($self->{'ELM_type'} eq "NONE")
3577             {
3578 0           $self->{'port'} = -1;
3579 0           die "Couldn't find an ELM module!\n";
3580             }
3581             }
3582            
3583            
3584             #*****************************************************************
3585            
3586             =head2 ConfigureDevice
3587            
3588             Set up the ELM module to return data in the required form.
3589            
3590             This function is called by 'new' and should not be called again.
3591            
3592             $obd->ConfigureDevice();
3593             =cut
3594            
3595             sub ConfigureDevice
3596             {
3597 0     0 1   my ($self) = @_;
3598            
3599 0 0         if ($self->{'debug_level'} > 0) { print "ConfigureDevice\n"; }
  0            
3600            
3601 0 0         if ($self->PortOK)
3602             {
3603 0           $self->Command("AT E0"); # Turn echo off
3604            
3605 0           $self->Command("AT L0"); # Turn linefeeds off
3606            
3607 0           $self->Command("AT SP 0"); # Set Protocol to auto
3608            
3609 0           $self->Command("AT DPN"); # Display Protocol number
3610            
3611 0           $self->Command("AT DP"); # Display Protocol
3612            
3613 0           $self->Command("AT H1"); # Turn headers on
3614            
3615 0           $self->Command("01 00"); # Prepare to talk and get available PID's
3616             }
3617             }
3618            
3619            
3620             #*****************************************************************
3621            
3622             =head2 FindAvailableCommands
3623            
3624             Query the ECU to find out which commands are supported and
3625             annotate the value entries in the 'get' structure with the
3626             'available' flag set to 0 (not supported) or 1 (supported).
3627            
3628             This function is called by 'new' and should not be called again.
3629            
3630             $obd->FindAvailableCommands();
3631             =cut
3632            
3633             sub FindAvailableCommands
3634             {
3635 0     0 1   my ($self) = @_;
3636            
3637 0           my @commands = ( "01 PIDs supported (01-20)",
3638             "02 PIDs supported (01-20)",
3639             "09 PIDs supported (01-20)"
3640             );
3641            
3642 0 0         if ($self->{'debug_level'} > 0) { print "FindAvailableCommands:\n"; }
  0            
3643            
3644 0 0         if ($self->{'bus_type'} eq "CAN")
3645             {
3646 0           push @commands, "06 MIDs supported (01-20)"; # Command only supported by CAN systems
3647             }
3648             else
3649             {
3650 0           push @commands, "05 TIDs supported (01-20)"; # Command only supported by non-CAN systems
3651             # push @commands, "06 TIDs supported (01-20)"; # Command only supported by non-CAN systems
3652             }
3653            
3654 0           foreach my $next_command (@commands)
3655             {
3656             do
3657 0           {
3658 0           $next_command = $self->ProcessAvailableCommands($next_command);
3659             } while (defined($next_command));
3660             }
3661             }
3662            
3663            
3664             #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3665            
3666             =head2 ProcessAvailableCommands
3667            
3668             Query the ECU to find out which commands are supported and
3669             annotate the value entries in the 'get' structure with the
3670             'available' flag set to 0 (not supported) or 1 (supported).
3671            
3672             This function is called by 'FindAvailableCommands' and should not be
3673             called by any other functions.
3674            
3675             $obd->ProcessAvailableCommands($command);
3676             =cut
3677            
3678             sub ProcessAvailableCommands
3679             {
3680 0     0 1   my ($self, $command) = @_;
3681            
3682 0           my $next_command = undef;
3683            
3684 0 0         if ($self->{'debug_level'} > 0) { print "~ProcessAvailableCommands: $command\n"; }
  0            
3685            
3686 0           $self->{'get'}->{$command}->{'available'} = 1; # Flag the command as available
3687            
3688 0           my $response = $self->Read($command);
3689            
3690 0 0         if ($self->{'debug_level'} > 1) { print "$command\n"; }
  0            
3691            
3692 0 0         if ($response->{'status'} eq "ok")
3693             {
3694 0           foreach my $result (@{$response->{'results'}})
  0            
3695             {
3696 0           $self->{'get'}->{$result->{'name'}}->{'available'} = $result->{'value'};
3697 0 0         if ($self->{'debug_level'} > 1) { print "$result->{'address'} - $result->{'name'}: $result->{'value'} $result->{'unit'}\n"; }
  0            
3698 0 0         if ($self->{'debug_level'} > 4)
3699             {
3700 0           print Dumper($result);
3701             }
3702            
3703             # print Dumper($self->{'get'}->{'Location of oxygen sensors 13'});
3704             # print Dumper($self->{'get'}->{'Location of oxygen sensors'});
3705            
3706 0 0 0       if (substr($result->{'name'}, 4, 15) eq "IDs supported (" && $result->{'value'} == 1)
    0 0        
      0        
3707             {
3708 0           $next_command = $result->{'name'};
3709             }
3710             elsif ( $result->{'value'} == 1 &&
3711             ((substr($result->{'name'}, -2, 2) eq "13" && $self->{'get'}->{'Location of oxygen sensors 13'}->{'available'} == 1)
3712             || (substr($result->{'name'}, -2, 2) eq "1D" && $self->{'get'}->{'Location of oxygen sensors 1D'}->{'available'} == 1))
3713             )
3714             {
3715 0           my $new_name = substr($result->{'name'}, 0, length($result->{'name'})-3);
3716            
3717 0 0         if ($self->{'debug_level'} > 2)
3718             {
3719 0           print "Old name: >$result->{'name'}<\n";
3720 0           print "New name: >$new_name<\n";
3721             }
3722            
3723 0 0 0       if ($result->{'name'} eq "Location of oxygen sensors 13" || $result->{'name'} eq "Location of oxygen sensors 1D")
3724             {
3725 0           $self->{'get'}->{$new_name} = $self->{'get'}->{$result->{'name'}};
3726             }
3727             else
3728             {
3729 0           $self->{'get'}->{$new_name} = delete($self->{'get'}->{$result->{'name'}});
3730             }
3731 0 0         if ($self->{'debug_level'} > 3)
3732             {
3733 0           print Dumper($self->{'get'}->{$new_name});
3734             }
3735             }
3736             }
3737             }
3738             else
3739             {
3740             # Flag command as unavailable
3741 0           $self->{'get'}->{$command}->{'available'} = 0;
3742             }
3743            
3744 0           return $next_command;
3745             }
3746            
3747            
3748             #*****************************************************************
3749            
3750            
3751             =head2 Replay
3752            
3753             Process a file containing debugging output and replay the commands
3754             through the module.
3755            
3756             This function is called by 'new' and should not be called by other functions.
3757            
3758             $obd->Replay($replay_filename);
3759             =cut
3760            
3761             sub Replay
3762             {
3763 0     0 1   my ($self, $replay_filename) = @_;
3764 0           $self->{'replay_file'} = 1;
3765            
3766 0           my $status = "ok";
3767 0           my $replay_command="";
3768            
3769             # Open the file containing the command and response data
3770 0           open (REPLAYFILE, $replay_filename);
3771            
3772 0           my $get_command = 0;
3773 0           my $seek_response = 1;
3774 0           my $read_response = 2;
3775 0           my $get_result = 4;
3776            
3777 0           my $replay_state = $get_command;
3778            
3779 0           while ()
3780             {
3781             # Iterate through issuing commands and parsing responses
3782 0           $_ =~ s/\r?\n//g; # Strip all carriage returns
3783            
3784 0 0         if ($replay_state == $get_command)
    0          
    0          
3785             {
3786 0 0         if (substr($_, 0, 1) eq "~")
3787             {
3788 0           $_ = substr($_, 1);
3789 0           my @linepart = split(":", $_);
3790 0           foreach my $part (@linepart)
3791             {
3792 0           $part =~ s/^\s+|\s+$//g; # Strip unwanted whitespace
3793             }
3794            
3795 0           $replay_command = '$self->'.$linepart[0]."(\"";
3796 0           my $number_of_parameters = scalar(@linepart);
3797 0           for (my $index=1; $index<$number_of_parameters; $index++)
3798             {
3799 0           $replay_command .= $linepart[$index];
3800 0 0         if ($index < ($number_of_parameters-1))
3801             {
3802 0           $replay_command .= ",";
3803             }
3804             }
3805 0           $replay_command .= "\");";
3806 0           $replay_state = $seek_response;
3807             }
3808             }
3809             elsif ($replay_state == $seek_response)
3810             {
3811 0 0         if ($_ eq "Response")
3812             {
3813 0           $replay_state = $read_response;
3814             }
3815             }
3816             elsif ($replay_state == $read_response)
3817             {
3818 0 0         if ($_ eq "End of response")
3819             {
3820             # Execute the command we just got the response to...
3821 0           $status = "ok";
3822 0           $status = eval($replay_command);
3823 0 0         if ($self->{'debug_level'} > 1)
3824             {
3825 0           print "Status: ";
3826 0           print Dumper($status);
3827 0           print "\n";
3828             }
3829 0           $replay_state = $get_command;
3830             }
3831             else
3832             {
3833 0 0         if (length($_) > 0)
3834             {
3835 0           push @{$self->{'replay_response'}}, $_;
  0            
3836             }
3837             }
3838             }
3839             }
3840 0           close (REPLAYFILE);
3841             }
3842            
3843            
3844             #*****************************************************************
3845            
3846             =head1 AUTHOR
3847            
3848             Alister Perrott, C<< >>
3849            
3850             =head1 BUGS
3851            
3852             Please report any bugs or feature requests to C, or through
3853             the web interface at L.
3854             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
3855            
3856             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.
3857             e.g. perl myOBD.pl&>trace.txt
3858            
3859            
3860             =head1 SUPPORT
3861            
3862             You can find documentation for this module with the perldoc command.
3863            
3864             perldoc Device::ELM327
3865            
3866            
3867             You can also look for information at:
3868            
3869             =over 5
3870            
3871             =item * RT: CPAN's request tracker
3872            
3873             L
3874            
3875             =item * AnnoCPAN: Annotated CPAN documentation
3876            
3877             L
3878            
3879             =item * CPAN Ratings
3880            
3881             L
3882            
3883             =item * Search CPAN
3884            
3885             L
3886            
3887             =item * My ELM327 page
3888            
3889             L
3890            
3891             =back
3892            
3893            
3894             =head1 ACKNOWLEDGEMENTS
3895            
3896             Many thanks to:
3897             The authors of Win32::SerialPort and Device::SerialPort.
3898             Kedar Warriner, Thomas Kaiser and Jason McCarver for their patches
3899             and suggestions for improvements.
3900             George R Ahearn for sending sample SAE J1979 debug information.
3901             Larry Wall and all the other people who have worked on Perl.
3902             ELM Electronics for creating the ELM327 module.
3903             Everyone involved with CPAN.
3904            
3905             =head1 LICENSE AND COPYRIGHT
3906            
3907             Copyright 2012-15 Alister Perrott.
3908            
3909             This program is free software; you can redistribute it and/or modify it
3910             under the terms of either: the GNU General Public License as published
3911             by the Free Software Foundation; or the Artistic License.
3912            
3913             See http://dev.perl.org/licenses/ for more information.
3914            
3915            
3916             =cut
3917            
3918             #********************************************************************
3919             1; # End of Device::ELM327 - Return success to require/use statement
3920             #********************************************************************
3921