1 #!/usr/bin/env python
2###########################################################################
3# obd_sensors.py
4#
5# Copyright 2004 Donour Sizemore (donour@uchicago.edu)
6# Copyright 2009 Secons Ltd. (www.obdtester.com)
7#
8# This file is part of pyOBD.
9#
10# pyOBD is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# pyOBD is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with pyOBD; if not, write to the Free Software
22# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23###########################################################################
24
25def hex_to_int(str):
26    i = eval("0x" + str, {}, {})
27    return i
28
29def maf(code):
30    code = hex_to_int(code)
31    return code * 0.00132276
32
33def throttle_pos(code):
34    code = hex_to_int(code)
35    return code * 100.0 / 255.0
36
37def intake_m_pres(code): # in kPa
38    code = hex_to_int(code)
39    return code / 0.14504
40
41def rpm(code):
42    code = hex_to_int(code)
43    return code / 4
44
45def speed(code):
46    code = hex_to_int(code)
47    return code / 1.609
48
49def percent_scale(code):
50    code = hex_to_int(code)
51    return code * 100.0 / 255.0
52
53def timing_advance(code):
54    code = hex_to_int(code)
55    return (code - 128) / 2.0
56
57def sec_to_min(code):
58    code = hex_to_int(code)
59    return code / 60
60
61def temp(code):
62    code = hex_to_int(code)
63    return code - 40
64
65def cpass(code):
66    #fixme
67    return code
68
69def fuel_trim_percent(code):
70    code = hex_to_int(code)
71    return (code - 128.0) * 100.0 / 128
72
73def dtc_decrypt(code):
74    #first byte is byte after PID and without spaces
75    num = hex_to_int(code[:2]) #A byte
76    res = []
77
78    if num & 0x80: # is mil light on
79        mil = 1
80    else:
81        mil = 0
82
83    # bit 0-6 are the number of dtc's.
84    num = num & 0x7f
85
86    res.append(num)
87    res.append(mil)
88
89    numB = hex_to_int(code[2:4]) #B byte
90
91    for i in range(0,3):
92        res.append(((numB>>i)&0x01)+((numB>>(3+i))&0x02))
93
94    numC = hex_to_int(code[4:6]) #C byte
95    numD = hex_to_int(code[6:8]) #D byte
96
97    for i in range(0,7):
98        res.append(((numC>>i)&0x01)+(((numD>>i)&0x01)<<1))
99
100    res.append(((numD>>7)&0x01)) #EGR SystemC7  bit of different
101
102    return res
103
104def hex_to_bitstring(str):
105    bitstring = ""
106    for i in str:
107        # silly type safety, we don't want to eval random stuff
108        if type(i) == type(''):
109            v = eval("0x%s" % i)
110            if v & 8 :
111                bitstring += '1'
112            else:
113                bitstring += '0'
114            if v & 4:
115                bitstring += '1'
116            else:
117                bitstring += '0'
118            if v & 2:
119                bitstring += '1'
120            else:
121                bitstring += '0'
122            if v & 1:
123                bitstring += '1'
124            else:
125                bitstring += '0'
126    return bitstring
127
128class Sensor:
129    def __init__(self,sensorName, sensorcommand, sensorValueFunction, u):
130        self.name = sensorName
131        self.cmd  = sensorcommand
132        self.value= sensorValueFunction
133        self.unit = u
134
135SENSORS = [
136    Sensor("          Supported PIDs", "0100", hex_to_bitstring  ,""       ),
137    Sensor("Status Since DTC Cleared", "0101", dtc_decrypt       ,""       ),
138    Sensor("DTC Causing Freeze Frame", "0102", cpass             ,""       ),
139    Sensor("      Fuel System Status", "0103", cpass             ,""       ),
140    Sensor("   Calculated Load Value", "0104", percent_scale     ,""       ),
141    Sensor("     Coolant Temperature", "0105", temp              ,"C"      ),
142    Sensor("    Short Term Fuel Trim", "0106", fuel_trim_percent ,"%"      ),
143    Sensor("     Long Term Fuel Trim", "0107", fuel_trim_percent ,"%"      ),
144    Sensor("    Short Term Fuel Trim", "0108", fuel_trim_percent ,"%"      ),
145    Sensor("     Long Term Fuel Trim", "0109", fuel_trim_percent ,"%"      ),
146    Sensor("      Fuel Rail Pressure", "010A", cpass             ,""       ),
147    Sensor("Intake Manifold Pressure", "010B", intake_m_pres     ,"psi"    ),
148    Sensor("              Engine RPM", "010C", rpm               ,""       ),
149    Sensor("           Vehicle Speed", "010D", speed             ,"MPH"    ),
150    Sensor("          Timing Advance", "010E", timing_advance    ,"degrees"),
151    Sensor("         Intake Air Temp", "010F", temp              ,"C"      ),
152    Sensor("     Air Flow Rate (MAF)", "0110", maf               ,"lb/min" ),
153    Sensor("       Throttle Position", "0111", throttle_pos      ,"%"      ),
154    Sensor("    Secondary Air Status", "0112", cpass             ,""       ),
155    Sensor("  Location of O2 sensors", "0113", cpass             ,""       ),
156    Sensor("        O2 Sensor: 1 - 1", "0114", fuel_trim_percent ,"%"      ),
157    Sensor("        O2 Sensor: 1 - 2", "0115", fuel_trim_percent ,"%"      ),
158    Sensor("        O2 Sensor: 1 - 3", "0116", fuel_trim_percent ,"%"      ),
159    Sensor("        O2 Sensor: 1 - 4", "0117", fuel_trim_percent ,"%"      ),
160    Sensor("        O2 Sensor: 2 - 1", "0118", fuel_trim_percent ,"%"      ),
161    Sensor("        O2 Sensor: 2 - 2", "0119", fuel_trim_percent ,"%"      ),
162    Sensor("        O2 Sensor: 2 - 3", "011A", fuel_trim_percent ,"%"      ),
163    Sensor("        O2 Sensor: 2 - 4", "011B", fuel_trim_percent ,"%"      ),
164    Sensor("         OBD Designation", "011C", cpass             ,""       ),
165    Sensor("  Location of O2 sensors", "011D", cpass             ,""       ),
166    Sensor("        Aux input status", "011E", cpass             ,""       ),
167    Sensor(" Time Since Engine Start", "011F", sec_to_min        ,"min"    ),
168    Sensor("  Engine Run with MIL on", "014E", sec_to_min        ,"min"    ),
169
170    ]
171
172
173#___________________________________________________________
174
175def test():
176    for i in SENSORS:
177        print i.name, i.value("F")
178
179if __name__ == "__main__":
180    test()
181