Skip to content

Commit d454521

Browse files
committed
check_voltage argument on OBD and Async
Added check_voltage optional argument that is `True` by default and when set to `False` disables the detection of the car supply voltage on OBDII port (which should be about 12V). This control assumes that, if the voltage is lower than 6V, the OBDII port is disconnected from the car. If the option is enabled, it adds the `OBDStatus.OBD_CONNECTED` status, which is set when enough voltage is returned (socket connected to the car) but the ignition is off (no communication with the vehicle). Setting the option to `False` should be needed when the adapter does not support the voltage pin or more generally when the hardware provides unreliable results, or if the pin reads the switched ignition voltage rather than the battery positive (this depends on the car).
1 parent a372044 commit d454521

5 files changed

Lines changed: 48 additions & 13 deletions

File tree

docs/Connections.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ connection = obd.OBD(ports[0]) # connect to the first port in the list
2020

2121
<br>
2222

23-
### OBD(portstr=None, baudrate=None, protocol=None, fast=True, timeout=0.1):
23+
### OBD(portstr=None, baudrate=None, protocol=None, fast=True, timeout=0.1, check_voltage=True):
2424

2525
`portstr`: The UNIX device file or Windows COM Port for your adapter. The default value (`None`) will auto select a port.
2626

@@ -37,6 +37,8 @@ Disabling fast mode will guarantee that python-OBD outputs the unaltered command
3737

3838
`timeout`: Specifies the connection timeout in seconds.
3939

40+
`check_voltage`: Optional argument that is `True` by default and when set to `False` disables the detection of the car supply voltage on OBDII port (which should be about 12V). This control assumes that, if the voltage is lower than 6V, the OBDII port is disconnected from the car. If the option is enabled, it adds the `OBDStatus.OBD_CONNECTED` status, which is set when enough voltage is returned (socket connected to the car) but the ignition is off (no communication with the vehicle). Setting the option to `False` should be needed when the adapter does not support the voltage pin or more generally when the hardware provides unreliable results, or if the pin reads the switched ignition voltage rather than the battery positive (this depends on the car).
41+
4042
<br>
4143

4244
---
@@ -58,7 +60,7 @@ r = connection.query(obd.commands.RPM) # returns the response from the car
5860

5961
### status()
6062

61-
Returns a string value reflecting the status of the connection. These values should be compared against the `OBDStatus` class. The fact that they are strings is for human readability only. There are currently 3 possible states:
63+
Returns a string value reflecting the status of the connection after OBD() or Async() methods are executed. These values should be compared against the `OBDStatus` class. The fact that they are strings is for human readability only. There are currently 4 possible states:
6264

6365
```python
6466
from obd import OBDStatus
@@ -69,11 +71,21 @@ OBDStatus.NOT_CONNECTED # "Not Connected"
6971
# successful communication with the ELM327 adapter
7072
OBDStatus.ELM_CONNECTED # "ELM Connected"
7173

72-
# successful communication with the ELM327 and the vehicle
74+
# successful communication with the ELM327 adapter,
75+
# OBD port connected to the car, ignition off
76+
# (not available with argument "check_voltage=False")
77+
OBDStatus.OBD_CONNECTED # "OBD Connected"
78+
79+
# successful communication with the ELM327 and the
80+
# vehicle; ignition on
7381
OBDStatus.CAR_CONNECTED # "Car Connected"
7482
```
7583

76-
The middle state, `ELM_CONNECTED` is mostly for diagnosing errors. When a proper connection is established, you will never encounter this value.
84+
The status is set by `OBD()` or `Async()` methods and remains unmodified during the connection. `status()` shall not be checked after the queries to verify that the connection is kept active.
85+
86+
`ELM_CONNECTED` and `OBD_CONNECTED` are mostly for diagnosing errors. When a proper connection is established with the vehicle, you will never encounter these values.
87+
88+
The ELM327 controller allows OBD Commands and AT Commands. In general, OBD Commands (which interact with the car) can be succesfully performed when the ignition is on, while AT Commands (which generally interact with the ELM327 controller) are always accepted. As the connection phase (for both `OBD` and `Async` objects) also performs OBD protocol commands (after the initial set of AT Commands) and returns the “Car Connected” status (“CAR_CONNECTED”) if the overall connection phase is successful, this status means that the serial communication is valid, that the ELM327 adapter is appropriately responding, that the OBDII socket is connected to the car and also that the ignition is on. “OBD Connected” status (“OBD_CONNECTED”) is returned when the OBDII socket is connected and the ignition is off, while the "ELM Connected" status (“ELM_CONNECTED”) means that the ELM327 processor is reached but the OBDII socket is not connected to the car. “OBD Connected” is controlled by the `check_voltage` option that by default is set to `True` and gets the ignition status when the socket is connected. If the OBDII socket does not support the unswitched battery positive supply, or the OBDII adapter cannot detect it, then the `check_voltage` option should be set to `False`; in such case, the "ELM Connected" status is returned when the socket is not connected or when the ignition is off, with no differentiation.
7789

7890
---
7991

obd/asynchronous.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ class Async(OBD):
4646
"""
4747

4848
def __init__(self, portstr=None, baudrate=None, protocol=None, fast=True,
49-
timeout=0.1):
49+
timeout=0.1, check_voltage=True):
5050
super(Async, self).__init__(portstr, baudrate, protocol, fast,
51-
timeout)
51+
timeout, check_voltage)
5252
self.__commands = {} # key = OBDCommand, value = Response
5353
self.__callbacks = {} # key = OBDCommand, value = list of Functions
5454
self.__thread = None

obd/elm327.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ class ELM327:
103103

104104

105105

106-
def __init__(self, portname, baudrate, protocol, timeout):
106+
def __init__(self, portname, baudrate, protocol, timeout,
107+
check_voltage=True):
107108
"""Initializes port by resetting device and gettings supported PIDs. """
108109

109110
logger.info("Initializing ELM327: PORT=%s BAUD=%s PROTOCOL=%s" %
@@ -168,6 +169,22 @@ def __init__(self, portname, baudrate, protocol, timeout):
168169
# by now, we've successfuly communicated with the ELM, but not the car
169170
self.__status = OBDStatus.ELM_CONNECTED
170171

172+
# -------------------------- AT RV (read volt) ------------------------
173+
if check_voltage:
174+
r = self.__send(b"AT RV")
175+
if not r or len(r) != 1 or r[0] == '':
176+
self.__error("No answer from 'AT RV'")
177+
return
178+
try:
179+
if float(r[0].lower().replace('v', '')) < 6:
180+
logger.error("OBD2 socket disconnected")
181+
return
182+
except ValueError as e:
183+
self.__error("Incorrect response from 'AT RV'")
184+
return
185+
# by now, we've successfuly connected to the OBD socket
186+
self.__status = OBDStatus.OBD_CONNECTED
187+
171188
# try to communicate with the car, and load the correct protocol parser
172189
if self.set_protocol(protocol):
173190
self.__status = OBDStatus.CAR_CONNECTED
@@ -178,7 +195,11 @@ def __init__(self, portname, baudrate, protocol, timeout):
178195
self.__protocol.ELM_ID,
179196
))
180197
else:
181-
logger.error("Connected to the adapter, but failed to connect to the vehicle")
198+
if self.__status == OBDStatus.OBD_CONNECTED:
199+
logger.error("Adapter connected, but the ignition is off")
200+
else:
201+
logger.error("Connected to the adapter, "\
202+
"but failed to connect to the vehicle")
182203

183204

184205
def set_protocol(self, protocol):

obd/obd.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class OBD(object):
5050
"""
5151

5252
def __init__(self, portstr=None, baudrate=None, protocol=None, fast=True,
53-
timeout=0.1):
53+
timeout=0.1, check_voltage=True):
5454
self.interface = None
5555
self.supported_commands = set(commands.base_commands())
5656
self.fast = fast # global switch for disabling optimizations
@@ -60,12 +60,13 @@ def __init__(self, portstr=None, baudrate=None, protocol=None, fast=True,
6060
self.__frame_counts = {} # keeps track of the number of return frames for each command
6161

6262
logger.info("======================= python-OBD (v%s) =======================" % __version__)
63-
self.__connect(portstr, baudrate, protocol) # initialize by connecting and loading sensors
63+
self.__connect(portstr, baudrate, protocol,
64+
check_voltage) # initialize by connecting and loading sensors
6465
self.__load_commands() # try to load the car's supported commands
6566
logger.info("===================================================================")
6667

6768

68-
def __connect(self, portstr, baudrate, protocol):
69+
def __connect(self, portstr, baudrate, protocol, check_voltage):
6970
"""
7071
Attempts to instantiate an ELM327 connection object.
7172
"""
@@ -82,14 +83,14 @@ def __connect(self, portstr, baudrate, protocol):
8283
for port in portnames:
8384
logger.info("Attempting to use port: " + str(port))
8485
self.interface = ELM327(port, baudrate, protocol,
85-
self.timeout)
86+
self.timeout, check_voltage)
8687

8788
if self.interface.status() >= OBDStatus.ELM_CONNECTED:
8889
break # success! stop searching for serial
8990
else:
9091
logger.info("Explicit port defined")
9192
self.interface = ELM327(portstr, baudrate, protocol,
92-
self.timeout)
93+
self.timeout, check_voltage)
9394

9495
# if the connection failed, close it
9596
if self.interface.status() == OBDStatus.NOT_CONNECTED:

obd/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class OBDStatus:
4646

4747
NOT_CONNECTED = "Not Connected"
4848
ELM_CONNECTED = "ELM Connected"
49+
OBD_CONNECTED = "OBD Connected"
4950
CAR_CONNECTED = "Car Connected"
5051

5152

0 commit comments

Comments
 (0)