2016-01-12 33 views
0

我想取一些數據OBD並試圖像通過this article 的製品(使用python 2.7)中描述道:的Python OBD編碼

的ELM327裝置HEX返回值。

爲了讀你在Python類型speed_hex = ser.readline剛要求的值()分裂( ' ')

轉換的HEX通過使用爲十進制:速度=浮子(INT('。0X' + speed_hex [3],0))

但我從我的OBD得到的答案不包含任何空格,而且他們看起來並不像他們有任何意義。

['\xd0MA\r?\r\r>\xd0\x15\r?\r\r>\x981\xf0\n'] 

所以我放棄了這種方法,而是改爲使用Python 3。

然後我寫了由this SO post

激發了小腳本但是我改成了定期拉大量的數據,並添加時間戳,一起被保存到CSV文件 - 作爲路徑意味着我的工作Windows(準確的說是10),COM配置正確,並且汽車符合OBD標準。

現在,當我運行我的腳本將打印出它的閱讀:

b'h\xf4\rSTOPPED\r\r>' 

,然後告訴我

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 

我不明白,編碼肯定是一個問題,但這個字符串不很有意義。即使我仔細看看0xf4 - 它只會是244(十進制),這不是靠近明智的RPM數據的地方。

爲什麼它在the other script工作呢?它不能成爲Windows的問題,可以嗎?

任何人都可以請幫助我理解這裏發生了什麼?

這是我的代碼。

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('ATSP0\r\n', encoding = 'utf-8')) 
ser.timeout = 1 

ser.write(bytes('ATE0\r\n', 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) + '\r\n', 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() 

如果是的任何權益:我使用通過USB接口,這似乎與SCANTOOL軟件flawlesly工作的ELM327兼容的設備,我的車是內置2000和ECU是大衆的。對已停止信息

回答

1

答案是關鍵字協議。所以,如果有人想知道同樣的問題:

在浪費10分鐘的生活之前:不,我不提供代碼解決方案。我只知道,爲什麼它不起作用。所以在這裏你只能找到協議的描述。感興趣的讀者可參考Konrad Reif的Springer Bosch Mechatronic系列的

在早期的協議(90年代)中,有ISO 9141和ISO 14230所描述的K線協議。大衆使用K線在千禧年左右在兩種方式中實現。測試車輛是一個2000年建立的VAG模型,根據數據給出的汽車預計將具有OBD II - 但沒有CAN-和關鍵字協議KWP1282或ISO14230 KWP2000的ISO9141。經過一些更多的研究後,汽車實現了ISO9140 KWP1281。 KWP1281的一個主要問題是初始化,因爲K線和L線使用5波特信號進行喚醒。喚醒請求看起來如下:

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

的測試器發出在地址0x33每秒5個比特的初始化請求。一旦車輛的ECU驗證了地址(在時間W1之後),在0x55發送一個確認信號,即所謂的同步字節。這個同步字節告訴測試者通信發生的波特率,通常爲10400波特。當車輛等待(W2)時,測試儀重新配置波特率。經過時間W2後,車輛將兩個關鍵字節(08,08或94,94)發送到測試儀,延遲W3。這些關鍵字節描述了碰撞預防時間P2MIN,之後ECU正在檢查K線的下降沿。 [Reif,Automotive Mechatronics,BOSCH] 如果測試儀確認P2Min,則第二個關鍵字被反轉並返回到車輛。然後車輛將0x33的補數作爲確認發送給測試儀,發出信號以便進行交互。

ELM327芯片完全不支持KWP1281,它確實支持KWP2000,但在這種情況下,它僅僅作爲少數OBD2參數的傳輸問題,其餘部分是供應商特定的。就大衆汽車的排放法規而言,ELM327 KWP2000通過OBD2提供排放特定的故障代碼,但不再提供。

由於時間有限,我沒有打算實施一個解決方案,因爲已經有軟件可以用於大衆汽車,我的論文也沒有讓我花費時間。有一天我可能會。

隨着VW特定KKL適配器與VW軟件VCDS的結合,測試車輛的OBD最終能夠提供足夠的結果。VCDS(VAG-COM)具有緩慢但充分的記錄功能,並且包括用於結果評估的VAG-Scope軟件,導出格式爲CSV,該格式簡單且易於用大多數程序處理。測量的分辨率約爲3Hz,每秒讀取三個測量組,每個測量組有四個參數。

有興趣的讀者是由賴夫康拉德進一步信息所指的斯普林格博世機電系列。

對不起,我無法提供如何實現它的答案。但至少有一個關於爲什麼它可能不適用於你(大衆,斯柯達,奧迪,西雅特)的汽車的指南。