1
votes

I have a Raspberry Pi 3 and I'm trying to hook it up to my car's OBD. I've got a Veepeak Mini Bluetooth OBD2 Scanner and I've tested it works perfectly fine with Torque on Android.

[UPDATE AFTER UPDATING TO THE LATEST VERSION OF pythonOBD]

It turns out there was a commit a few days ago that introduced a delay at the 0100\r message. This was apparently done to mitigate against a particular set of OBD scanners that didn't respond in time at that particular message. I've cloned the repo and pulled the latest from master and changed the import line to this:

import sys
sys.path.insert(1, '/home/pi/python-OBD')
import obd

Now, while I was getting a separate set of logs, I was never able to get a hold of the car data. The auto protocol defaults to protocol 6 for some reason which outputs a CAN error after the 0100\r message. After setting it to protocol 5, the only one that had promising results, I'm getting those logs:

$> python obdtest.py 
[obd.obd] ======================= python-OBD (v0.7.1) =======================
[obd.obd] Using scan_serial to select port
[obd.obd] Available ports: ['/dev/rfcomm47']
[obd.obd] Attempting to use port: /dev/rfcomm47
[obd.elm327] Initializing ELM327: PORT=/dev/rfcomm47 BAUD=38400 PROTOCOL=5
[obd.elm327] write: 'ATZ\r'
[obd.elm327] wait: 1 seconds
[obd.elm327] read: b'ATZ\r\r\rELM327 v1.5\r\r>'
[obd.elm327] write: 'ATE0\r'
[obd.elm327] read: b'ATE0\rOK\r\r>'
[obd.elm327] write: 'ATH1\r'
[obd.elm327] read: b'OK\r\r>'
[obd.elm327] write: 'ATL0\r'
[obd.elm327] read: b'OK\r\r'
[obd.elm327] write: 'AT RV\r'
[obd.elm327] read: b'13.9V\r\r>'
[obd.elm327] write: 'ATTP5\r'
[obd.elm327] read: b'OK\r'
[obd.elm327] write: '0100\r'
[obd.elm327] read: b'>'
[obd.elm327] no response; wait: 0.100000 seconds
[obd.elm327] read: b'BUS INIT: OK'
[obd.protocols.protocol] map ECU 16 --> ENGINE
[obd.elm327] Connected Successfully: PORT=/dev/rfcomm47 BAUD=38400 PROTOCOL=5
[obd.obd] querying for supported commands
[obd.obd] Sending command: 0100: Supported PIDs [01-20]
[obd.elm327] write: '0100\r'
[obd.elm327] read: b'STOPPED\r\r>'
[obd.OBDCommand] 0100: Supported PIDs [01-20] did not receive any acceptable messages
[obd.obd] No valid data for PID listing command: 0100: Supported PIDs [01-20]
[obd.obd] Sending command: 0900: Supported PIDs [01-20]
[obd.elm327] write: '0900\r'
[obd.elm327] read: b'87 F1 10 49 00 01 30 00 00 00 02 \r\r>'
[obd.obd] finished querying with 8 commands supported
[obd.obd] ===================================================================
[obd.obd] '010C: Engine RPM' is not supported
None
[obd.obd] Closing connection
[obd.elm327] closing port
[obd.elm327] write: 'ATZ\r'

It looks like 0100\r is written twice and the logs return read: b'BUS INIT: OK' first and read: b'STOPPED\r\r>' second. The baudrate seems to work the same whether it's 38400 or 9600, so I don't think that's an issue either.

[Original question]

I've setup bluetooth on the Raspberry Pi and have paired the device, but when trying to run the following script, it works about 1 in 10 to 20 tries with the following logs:

import obd

obd.logger.setLevel(obd.logging.DEBUG)
connection = obd.OBD() # auto-connects to USB or RF port

cmd = obd.commands.RPM # select an OBD command (sensor)

response = connection.query(cmd) # send the command, and parse the response

print(response.value) # returns unit-bearing values thanks to Pint

connection.close()

When it fails (vast majority of time) it displays this:

$> python obdtest.py 
[obd.obd] ======================= python-OBD (v0.7.1) =======================
[obd.obd] Using scan_serial to select port
[obd.obd] Available ports: ['/dev/rfcomm47']
[obd.obd] Attempting to use port: /dev/rfcomm47
[obd.elm327] Initializing ELM327: PORT=/dev/rfcomm47 BAUD=auto PROTOCOL=auto
[obd.elm327] Response from baud 38400: '\x7f\x7f\r?\r\r>'
[obd.elm327] Choosing baud 38400
[obd.elm327] write: 'ATZ\r'
[obd.elm327] wait: 1 seconds
[obd.elm327] read: b'ATZ\r\r\rELM327 v1.5\r\r>'
[obd.elm327] write: 'ATE0\r'
[obd.elm327] read: b'ATE0\rOK\r\r>'
[obd.elm327] write: 'ATH1\r'
[obd.elm327] read: b'OK\r\r>'
[obd.elm327] write: 'ATL0\r'
[obd.elm327] read: b'OK\r\r>'
[obd.elm327] write: 'AT RV\r'
[obd.elm327] read: b'15.0V\r\r>'
[obd.elm327] write: 'ATSP0\r'
[obd.elm327] read: b'OK\r'
[obd.elm327] write: '0100\r'
[obd.elm327] read: b'>'
[obd.elm327] write: 'ATDPN\r'
[obd.elm327] read: b'SEARCHING...\r86 F1 10 41 00 BF BF F9 90 CF \r\r>'
[obd.elm327] Failed to retrieve current protocol
[obd.elm327] Adapter connected, but the ignition is off
[obd.obd] Cannot load commands: No connection to car
[obd.obd] ===================================================================
[obd.obd] '010C: Engine RPM' is not supported
None
[obd.obd] Closing connection
[obd.elm327] closing port
[obd.elm327] write: 'ATZ\r'

When it succeeds (1 in 10 or more tries) it displays this:

$> python obdtest.py 
[obd.obd] ======================= python-OBD (v0.7.1) =======================
[obd.obd] Using scan_serial to select port
[obd.obd] Available ports: ['/dev/rfcomm47']
[obd.obd] Attempting to use port: /dev/rfcomm47
[obd.elm327] Initializing ELM327: PORT=/dev/rfcomm47 BAUD=auto PROTOCOL=auto
[obd.elm327] Response from baud 38400: '\x7f\x7f\r?\r\r>'
[obd.elm327] Choosing baud 38400
[obd.elm327] write: 'ATZ\r'
[obd.elm327] wait: 1 seconds
[obd.elm327] read: b'ATZ\r\r\rELM327 v1.5\r\r>'
[obd.elm327] write: 'ATE0\r'
[obd.elm327] read: b'ATE0\rOK\r\r>'
[obd.elm327] write: 'ATH1\r'
[obd.elm327] read: b'OK\r\r>'
[obd.elm327] write: 'ATL0\r'
[obd.elm327] read: b'OK\r\r'
[obd.elm327] write: 'AT RV\r'
[obd.elm327] read: b'14.7V\r\r>'
[obd.elm327] write: 'ATSP0\r'
[obd.elm327] read: b'OK\r'
[obd.elm327] write: '0100\r'
[obd.elm327] read: b'SEARCHING...\r86 F1 10 41 00 BF BF F9 90 CF \r\r>'
[obd.elm327] write: 'ATDPN\r'
[obd.elm327] read: b'A5\r\r>'
[obd.protocols.protocol] map ECU 16 --> ENGINE
[obd.elm327] Connected Successfully: PORT=/dev/rfcomm47 BAUD=38400 PROTOCOL=5
[obd.obd] querying for supported commands
[obd.obd] Sending command: 0100: Supported PIDs [01-20]
[obd.elm327] write: '0100\r'
[obd.elm327] read: b'86 F1 10 41 00 BF BF F9 90 CF \r\r>'
[obd.obd] finished querying with 51 commands supported
[obd.obd] ===================================================================
[obd.obd] Sending command: 010C: Engine RPM
[obd.elm327] write: '010C\r'
[obd.elm327] read: b'84 F1 10 41 0C 08 3C 16 \r\r>'
527.0 revolutions_per_minute
[obd.obd] Closing connection
[obd.elm327] closing port
[obd.elm327] write: 'ATZ\r'

Note that 84 F1 10 41 0C 08 3C 16 is not the OBD scanner's MAC address. Also rfcomm47 is set manually to a random value, just happened to pick 47.

What's consistent about the success logs is the number of the protocol (5). I've seen somewhere else a suggestion to just keep trying to connect, but when I'm adding something like this

while len(connection.supported_commands) < 100:
    connection = obd.Async("/dev/rfcomm47", protocol = "5", baudrate = "38400", fast = False, timeout = 30)

I'm getting those logs every time it is called from the second time on:

$> python sandboxobd.py 
<<startup logs>>
[obd.elm327] write: 'ATDPN\r'
[obd.elm327] read: b'SEARCHING...\r86 F1 10 41 00 BF BF F9 90 CF \r\r>'
[obd.elm327] Failed to retrieve current protocol
[obd.elm327] Adapter connected, but the ignition is off
[obd.obd] Cannot load commands: No connection to car
[obd.obd] ===================================================================
[obd.obd] ======================= python-OBD (v0.7.1) =======================
<<startup logs>>
[obd.elm327] read: b'>'
[obd.elm327] write: 'ATDPN\r'
[obd.elm327] read: b'SEARCHING...\rUNABLE TO CONNECT\r\r>'
[obd.elm327] Failed to retrieve current protocol
[obd.elm327] Adapter connected, but the ignition is off
[obd.obd] Cannot load commands: No connection to car
[obd.obd] ===================================================================

With the second part repeating indefinitely. Connecting directly to protocol 5 using connection = obd.OBD(protocol="5") gives me this:

[obd.elm327] Connected Successfully: PORT=/dev/rfcomm47 BAUD=38400 PROTOCOL=5
[obd.obd] querying for supported commands
[obd.obd] Sending command: 0100: Supported PIDs [01-20]
[obd.elm327] write: '0100\r'
[obd.elm327] read: b'BUS INIT: STOPPED\r\r>'
[obd.OBDCommand] 0100: Supported PIDs [01-20] did not receive any acceptable messages
[obd.obd] No valid data for PID listing command: 0100: Supported PIDs [01-20]
[obd.obd] finished querying with 7 commands supported
[obd.obd] ===================================================================
[obd.obd] '010C: Engine RPM' is not supported
None
[obd.obd] Closing connection
[obd.elm327] closing port
[obd.elm327] write: 'ATZ\r'

Did anybody encounter this issue before? I can't think of anything to else to try and see if it works. Any help would be greately appreciated.

1
What version of the library are you using? Try latest from github.paiv
I spot two differences: 1.) in the successful log on line 19, it states read: b'14.7V\r\r> while on the unsuccessful it's 15.0V. 2.) on the successful logs it's first reading the searching part and then writing, whil on the unsuccessful it's the other way around. Does especially part 1.) only happen by chance? Can it be forced? I must admit I have no idea of all of this, just pointing out probably obvious stuff :)Tobias Brösamle
The library has version 0.7.1 as shown in the logs. I've tried the latest master version by replacing import obd in the script with with httpimport.github_repo('brendan-w', 'python-OBD', branch = 'master'): import obd (after installing and importing httpimport via pip of course). The logs and behavior were identical as in the question.user2565010
As far as the voltage is concerned, it does vary within 1V of 15V with every run of the script, but I've had successful and unsuccessful runs with the exact same voltage. I'm not sure if I can do the handshake sequence any better, which is why I wondered if there is a way to retry part of the traffic attempts from the pi without restarting the whole connection. Or maybe the logs point to a deeper issue.user2565010
@user2565010 I still don't think you are using the latest library. Uninstall obd before using httpimportpaiv

1 Answers

0
votes

Since you're specifying the protocol, in elm327.py you'll want to modify

r0100 = self.__send(b"0100") in function

def manual_protocol(self, protocol_): to

r0100 = self.__send(b"0100", delay=1) Roughly line 224.

The commit you reference only adds the delay when protocol is not specified. ie: protocol=auto

Adding the delay helps but it's not perfect. After the connection is established I check if obd.commands.SPEED is supported and if not start all over.

I've also added a delay=1 to all of the connection initialization commands (from ATZ to ATDPN) because I find without it one of them will randomly fail, the delay seems to lower the failure rate.

Lastly. ELM327 v1.5 is a cheap clone, responses don't necessarily follow the standard.