Python OBD encoding

Question:

I wanted to fetch some OBD data and tried it like described by this article
The article (using python 2.7) said:

The elm327 device returns values in HEX.

To read the value you just requested in Python type speed_hex = ser.readline().split(‘ ‘)

Convert the HEX to decimal by using: speed = float(int(‘0x’+speed_hex[3], 0 ))

But the answers I get from my OBD do not contain any whitespace furthermore they didn’t look like they made any sense at all.

 ['xd0MAr?rr>xd0x15r?rr>x981xf0n'] 

so I gave up on this approach and oved to Python 3 instead.

I then wrote a little script inspired by this SO post

However I changed it to pull a lot of data periodically and added a timestamp, all together is saved to a csv file – as the path implies I am working on Windows (10 to be precise), COM is correctly configured and the car is OBD compliant.

Now when I run my script it prints out what it read:

b'hxf4rSTOPPEDrr>' 

and then tells me

Traceback (most recent call last):
File "python3test.py", line 36, in <module> r.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf4 in position 1:  
invalid continuation byte

I do understand that encoding certainly is an issue, but this string does not make much sense at all. even if I take a closer look at 0xf4 – it would only be 244 (dec) which is no where near sensible RPM data.

Why does it work in the other script then? It can’t be a Windows issue, can it?

Can anyone please help me understand whats going on in here?

Here is my code.

import serial
import time
import string
import io
import os
import sys
import datetime as dt


ser = serial.Serial("COM1")
ser.baudrate = 38400
ser.write(bytes('ATSP0rn', encoding = 'utf-8'))
ser.timeout = 1

ser.write(bytes('ATE0rn', encoding = 'utf-8'))
ser.timeout = 1

def millis_interval(start, end):
    '''start and end are datetime instances'''
    diff = end - start
    millis = diff.days * 24 * 60 * 60 * 1000
    millis += diff.seconds * 1000
    millis += diff.microseconds / 1000
    return millis

Testtime = str(dt.datetime.now()).split(' ')

PIDs = ["0C","0D","43","04","11","5C","05","10","46"]
response = []

''' open file and create header row'''
with open("C:/test/test_"+Testtime[0]+"_"+Testtime[1].replace(":","-")+".csv", "a") as myfile:
        myfile.write("Time,Timestep,RPM,Speed, AbsLoad, CalcLoad, ThrottlePos, CoolTemp, OilTemp, MAF, AmbAirTemp")


start = dt.datetime.now()    # need initial value
while 1:
    end = dt.datetime.now()
     
    myfile.write("n"+str(dt.datetime.now())+','+str(millis_interval(start,end))+)
    count = 0
    for s in PIDs:
        
        start = dt.datetime.now()
        ser.write(bytes(("01" + s) + 'rn', encoding = 'utf-8'))
        ser.timeout = 1
        ''' if answer not finished but new information sent OBD will stop writing and listen to UART *'''
        r = ser.read(999)
        while ">" not in r
             r = r + ser.read(999)
        print(r) # debug
        r.decode('utf-8')
        response[count] = r
        print(response[count]) #see what it looks like in utf-8
        
        myfile.write(str(','+response[count]))
        count +=1
ser.close()  

If it is of any interest: I am using an ELM327 compatible device via USB which seems to work flawlesly with the Scantool Software, my car is built 2000 and the ECU is a VW one.

Asked By: AnyOneElse

||

Answers:

The answer was the keyword protocol. So just in case anyone wonders about the same issues:

Before you waste 10 minutes of your life: No, I do not provide a code solution. I merely figured out, why it did not work. So here you will only find a description of the protocol. The interested reader is referred to the Springer Bosch Mechatronic Series by Konrad Reif.

Among the early protocols (1990s) there is the K-Line Protocol as described by ISO 9141 and ISO 14230. VW uses the K-Line which was implemented in cars around the millennium in two ways. The test vehicle was a 2000 built VAG Model, by the data given the car is expected to feature OBD II – yet no CAN – and ISO9141 with the key word protocol KWP1282 or ISO14230 KWP2000. After some more research it became clear that the car implements the ISO9140 KWP1281. One major problem with KWP1281 is the initialization as the K-Line and L-Line use 5 baud signals for wakeup. The wakeup request looks as follows:

Publisher: Springer, Bosch automotive series, Editor: Reif, Konrad, title: Automotive Mechatronics, year: 2014
Communication of tester and ECU

The tester issues the initialization request at address 0x33 with 5 bits per second. Once the vehicle’s ECU has validated the address (after time W1) a confirmation is sent to the tester at 0x55, the so called synchronization byte. This synchronization byte tells the tester the baud rate at which communication shall take place, usually 10400 baud. The tester then reconfigures the baud rate, while the vehicle waits (W2). After time W2 has passed the vehicle sends two key bytes (either 08,08 or 94,94) to the tester with a delay of W3. These key bytes describe the collision prevention time P2MIN after which an ECU is checking the K-Line for a falling edge. [Reif, Automotive Mechatronics, BOSCH]
If the tester acknowledges P2Min the second key byte is inverted and returned to the vehicle. The vehicle then sends the complement of 0x33 to the tester as confirmation, signaling ready for interaction.

The ELM327 chips do not support KWP1281 at all, it does support KWP2000 but in this case it simply serves as a matter of transport for a few OBD2 parameters, the rest is vendor specific. As far as emission legislation is concerned for VW vehicles the ELM327 KWP2000 delivers emission specific fault codes via OBD2 but no more.

Due to the limited time at hand, I did not bother to implement a solution as there already is software to do it for VW cars and my thesis did not allow me to spend the time. I might, one day.

With the VW specific KKL adapter in combination with VW software VCDS the OBD of the test vehicle finally delivers sufficient results.
VCDS (VAG-COM) features slow, yet sufficient recording capabilities and includes the VAG-Scope software for result evaluation, the export format is CSV which is simple and easy to process with a majority of programs. The resolution of the measurement is approximately 3Hz, reading three measurement groups with four parameters each per second.

The interested reader is referred to the Springer Bosch Mechatronic Series by Konrad Reif for further information.

Sorry I could not provide an answer on how to implement it. But at least a guide on why it might not work for your (VW, Skoda, Audi, Seat, …) car.

Answered By: AnyOneElse
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.