Skip to content

Commit

Permalink
Refactor PIDs and add result presenter
Browse files Browse the repository at this point in the history
  • Loading branch information
Trey Chandler committed Apr 26, 2014
1 parent 88f3bd4 commit 143a5df
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 55 deletions.
2 changes: 2 additions & 0 deletions lib/obd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

require_relative "obd/command"
require_relative "obd/connection"
require_relative "obd/pids"
require_relative "obd/result"

module OBD
def self.connect *args
Expand Down
52 changes: 10 additions & 42 deletions lib/obd/command.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
module OBD
class Command
include OBD::PIDs

def initialize

def self.add_pid(code, opts)
@@pids[code.to_sym] = opts
end

def self.format_result command, result
if is_command?(command) && result != "NO DATA"
pids[command.to_sym].call h(result), h(result).to_i(16)
OBD::Result.new(command,
@@pids[command.to_sym][:fmt].call(h(result), h(result).to_i(16)),
units: @@pids[command.to_sym][:unit]
)
else
result
end
end

def self.to_hex command
if is_command? command
"01%02x" % pids.keys.index(command.to_sym)
@@pids[command.to_sym][:pid]
else
command
end
end

def self.is_command? command
pids.keys.include? command.to_sym
@@pids.keys.include? command.to_sym
end

def self.pid
Expand All @@ -33,48 +37,12 @@ def self.pid
end

def self.pids
{
pids_supported_1: lambda {|x,d| d.to_s(2).split('').each_with_index.map{|b,i| pids.keys[i] if b == '1'}},
monitor_status_since_clear: lambda {|x| x},
freeze_dtc: lambda {|x| x},
fuel_system_status: lambda {|x| x},
calculated_engine_load: lambda {|x,d| "%0.2f" % (d * 100.0 / 255.0) + '%'},
engine_coolent_temperature: lambda {|x,d| "%0.2f" % (d * 1.8 - 104) + '*F'},
short_term_fuel_trim_bank_1: lambda {|x,d| "%0.2f" % (d * 0.78125 - 100) + '%'},
long_term_fuel_trim_bank_1: lambda {|x,d| "%0.2f" % (d * 0.78125 - 100) + '%'},
short_term_fuel_trim_bank_2: lambda {|x,d| "%0.2f" % (d * 0.78125 - 100) + '%'},
long_term_fuel_trim_bank_2: lambda {|x,d| "%0.2f" % (d * 0.78125 - 100) + '%'},
fuel_pressure: lambda {|x,d| "%0.2f" % (d * 3 * 0.145) + 'psi'},
intake_manifold_absolute_pressure: lambda {|x,d| "%0.2f" % (d * 0.145) + 'psi'},
engine_rpm: lambda {|x,d| "%0.2f" % (d / 4.0) + 'rpm'},
vehicle_speed: lambda {|x,d| "%0.2f" % (d * 0.621371192) + 'mph'},
timing_advance: lambda {|x,d| "%0.2f" % (d / 2.0 - 64) + '*'},
intake_air_temperature: lambda {|x,d| "%0.2f" % (d * 1.8 - 104) + '*F'},
maf_air_flow_rate: lambda {|x,d| "%0.2f" % (d / 100.0) + 'grams/sec'},
throttle_position: lambda {|x,d| "%0.2f" % (d * 100 / 255.0) + '%'},
commanded_secondary_air_status: lambda {|x| x}, # bit encoded
oxygen_sensors_present: lambda {|x| x}, # [A0..A3] == Bank 1,Sensors 1-4.[A4..A7]
bank_1_sensor_1_oxygen_sensor_voltage: lambda {|x| x},
bank_1_sensor_2_oxygen_sensor_voltage: lambda {|x| x},
bank_1_sensor_3_oxygen_sensor_voltage: lambda {|x| x},
bank_1_sensor_4_oxygen_sensor_voltage: lambda {|x| x},
bank_2_sensor_1_oxygen_sensor_voltage: lambda {|x| x},
bank_2_sensor_2_oxygen_sensor_voltage: lambda {|x| x},
bank_2_sensor_3_oxygen_sensor_voltage: lambda {|x| x},
bank_2_sensor_4_oxygen_sensor_voltage: lambda {|x| x},
obd_standards_vehicle_conforms_to: lambda {|x| x}, # bit encoded
oxygen_sensors_present_2: lambda {|x| x}, # complicated...
aux_input_status: lambda {|x| (x == 1).inspect}, # Power Take Off (PTO) status is active?
run_time_since_engine_start: lambda {|x,d| d}, # seconds
pids_supported_2: lambda {|x,d| d.to_s(2).split('').each_with_index.map{|b,i| pids.keys[i+33] if b == '1'}}, # bit encoded
distance_traveled_with_mil_on: lambda {|x,d| d.to_s + 'km'}
}
@@pids
end

def self.h response
response[4..-1]
end


end
end
8 changes: 6 additions & 2 deletions lib/obd/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ def initialize port, baud = 9600
end

def voltage
send("AT RV")
OBD::Result.new(
'Voltage',
send("AT RV").to_f,
units: 'V'
)
end

def connect
Expand All @@ -24,7 +28,7 @@ def connect

def [] command
OBD::Command.format_result(command, send(OBD::Command.to_hex(command)))
com = OBD::Command.new command
#com = OBD::Command.new command
end

def send data
Expand Down
201 changes: 201 additions & 0 deletions lib/obd/pids.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
module OBD
module PIDs
@@pids = {
pids_supported_1: {
pid: '0100',
fmt: lambda {|x,d| d.to_s(2).split('').each_with_index.map{|b,i| pids.keys[i] if b == '1'}}
},
monitor_status_since_clear: {
pid: '0101',
fmt: lambda {|x,d| x}
},
freeze_dtc: {
pid: '0102',
fmt: lambda {|x,d| x}
},
fuel_system_status: {
pid: '0103',
fmt: lambda {|x,d| x}
},
calculated_engine_load: {
pid: '0104',
fmt: lambda {|x,d| d * 100.0 / 255.0},
unit: '%'
},
engine_coolent_temperature: {
pid: '0105',
fmt: lambda {|x,d| d * 1.8 - 104},
unit: 'C'
},
short_term_fuel_trim_bank_1: {
pid: '0106',
fmt: lambda {|x,d| d * 0.78125 - 100},
unit: '%'
},
long_term_fuel_trim_bank_1: {
pid: '0107',
fmt: lambda {|x,d| d * 0.78125 - 100},
unit: '%'
},
short_term_fuel_trim_bank_2: {
pid: '0108',
fmt: lambda {|x,d| d * 0.78125 - 100},
unit: '%'
},
long_term_fuel_trim_bank_2: {
pid: '0109',
fmt: lambda {|x,d| d * 0.78125 - 100},
unit: '%'
},
fuel_pressure: {
pid: '010A',
fmt: lambda {|x,d| d * 3 * 0.145},
unit: 'psi'
},
intake_manifold_absolute_pressure: {
pid: '010B',
fmt: lambda {|x,d| d * 0.145},
unit: 'psi'
},
engine_rpm: {
pid: '010C',
fmt: lambda {|x,d| d / 4.0},
unit: 'rpm'
},
vehicle_speed: {
pid: '010D',
fmt: lambda {|x,d| d * 0.621371192},
unit: 'mph'
},
timing_advance: {
pid: '010E',
fmt: lambda {|x,d| d / 2.0 - 64},
unit: 'deg'
},
intake_air_temperature: {
pid: '010F',
fmt: lambda {|x,d| d * 1.8 - 104},
unit: 'C'
},
maf_air_flow_rate: {
pid: '0110',
fmt: lambda {|x,d| d / 100.0},
unit: 'grams/sec'
},
throttle_position: {
pid: '0111',
fmt: lambda {|x,d| d * 100 / 255.0},
unit: '%'
},
commanded_secondary_air_status: {
pid: '0112',
fmt: lambda {|x,d| x}
}, # bit enhexd
oxygen_sensors_present: {
pid: '0113',
fmt: lambda {|x,d| x}
},
# [A0..A3] == Bank 1,Sensors 1-4.[A4..A7]
bank_1_sensor_1_oxygen_sensor_voltage: {
pid: '0114',
fmt: lambda {|x,d| x},
unit: '%'
},
bank_1_sensor_2_oxygen_sensor_voltage: {
pid: '0115',
fmt: lambda {|x,d| x},
unit: '%'
},
bank_1_sensor_3_oxygen_sensor_voltage: {
pid: '0116',
fmt: lambda {|x,d| x},
unit: '%'
},
bank_1_sensor_4_oxygen_sensor_voltage: {
pid: '0117',
fmt: lambda {|x,d| x},
unit: '%'
},
bank_2_sensor_1_oxygen_sensor_voltage: {
pid: '0118',
fmt: lambda {|x,d| x},
unit: '%'
},
bank_2_sensor_2_oxygen_sensor_voltage: {
pid: '0119',
fmt: lambda {|x,d| x},
unit: '%'
},
bank_2_sensor_3_oxygen_sensor_voltage: {
pid: '011A',
fmt: lambda {|x,d| x},
unit: '%'
},
bank_2_sensor_4_oxygen_sensor_voltage: {
pid: '011B',
fmt: lambda {|x,d| x},
unit: '%'
},
obd_standards_vehicle_conforms_to: {
pid: '011C',
fmt: lambda {|x,d| x}
},
# bit encoded
oxygen_sensors_present_2: {
pid: '011D',
fmt: lambda {|x,d| x}
},
# complicated...
aux_input_status: {
pid: '011E',
fmt: lambda {|x,d| (x == 1).inspect}
},
# Power Take Off (PTO) status is active?
run_time_since_engine_start: {
pid: '011F',
fmt: lambda {|x,d| d}
},
# seconds
pids_supported_2: {
pid: '0120',
fmt: lambda {|x,d| d.to_s(2).split('').each_with_index.map{|b,i| pids.keys[i+33] if b == '1'}}
},
# bit encoded
distance_traveled_with_mil_on: {
pid: '0121',
fmt: lambda {|x,d| d.to_s},
unit: 'km'
},
fuel_level_input: {
pid: '012F',
fmt: lambda {|x,d| d * 100.0 / 255.0 },
unit: '%'
},
barometric_pressure: {
pid: '0133',
fmt: lambda {|x,d| x },
unit: 'kPa'
},
ambient_air_temperature: {
pid: '0166',
fmt: lambda {|x,d| x - 40 },
unit: 'C'
},
engine_oil_temperature: {
pid: '015C',
fmt: lambda {|x,d| x - 40 },
unit: 'C'
},
engine_fuel_rate: {
pid: '015E',
fmt: lambda {|x,d| },
unit: 'L/h'
}
# code: {
# pid: '',
# fmt: lambda {|x,d| },
# unit: ''
# },
}
end
end
36 changes: 36 additions & 0 deletions lib/obd/result.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module OBD
# Presenter for results
class Result
attr_accessor :value, :code, :opts

@@defaults = {
precision: 2
}

def self.set_defaults(opts = {})
@@defaults.merge!(opts)
end

def initialize(code, value, opts = {})
@code = code
@value = value
@opts = @@defaults.dup.merge(opts)
end

def to_s(opts = {})
opts = opts.merge(@opts)

val = if opts[:precision] && @value.kind_of?(Float)
"%0.#{opts[:precision]}f" % @value
else
@value
end

[val.to_s, opts[:units]].compact.join()
end

def inspect
"#{@code} => #{to_s}"
end
end
end
35 changes: 24 additions & 11 deletions sample.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
require 'obd'
require './lib/obd'

OBD_DEVICE = '/dev/tty.SLAB_USBtoUART' #'/dev/tty.obd'
OBD_BAUD = 38400

print "Opening OBDII connection..."
obd = OBD.connect OBD_DEVICE, OBD_BAUD
puts 'OK'

# OBD::Command.add_pid :oil_pressure, {
# pid: 'F043',
# fmt: lambda {|x,d| (d.to_f * 3.2) - 1.6 },
# unit: 'psi'
# }

obd = OBD.connect "/dev/tty.obd", 38400

loop do
puts obd[:engine_rpm],
obd[:vehicle_speed],
obd.voltage,
obd[:timing_advance] + " - Timing Advance",
obd[:engine_coolent_temperature] + " - Engine Coolant Temperature",
obd[:calculated_engine_load] + " - Calculated Engine Load",
obd[:throttle_position] + " - Throttle Position",
obd[:aux_input_status] + " - Aux input status",
'-------------------------------'

puts "\033[2J\033[0;0H", # Clear screen and return cursor to 0,0
obd[:engine_rpm].inspect,
obd[:vehicle_speed].inspect,
obd.voltage.inspect,
obd[:timing_advance].inspect,
obd[:engine_coolent_temperature].inspect,
obd[:calculated_engine_load].inspect,
obd[:throttle_position].inspect,
obd[:aux_input_status]
end

0 comments on commit 143a5df

Please sign in to comment.