2026年11月13日 星期五

Reading an OBD-II ECU Simulator with PCAN in the ATS Console and Feeding Live Vehicle Speed to a Geotab IOX Device | ATS 操作台讀行車電腦模擬器:OBD-II 掃描視窗、PCAN 實測,把即時車速餵給 Geotab IOX 車機

測車機(行車記錄器這類接在車上的裝置)時,常常需要「車子正在跑」的資料:車速、轉速、里程。實車不方便,所以手邊有一台行車電腦模擬器,它是一顆假的引擎 ECU,接上 OBD 診斷就會回車速、轉速,數值用旋鈕轉。這次在自己寫的 ATS 網頁操作台裡加了一個獨立的 OBD-II 掃描視窗,用 PCAN 讀模擬器的參數,再把讀到的車速當成 Geotab GO 的車輛資料,送給走 Geotab IOX 協定的車機。這篇記錄做法、實測數字和踩到的坑。

行車電腦模擬器 IMSB5010

這台是 imsapp 的 OBD2 ECU Simulator(型號 IMSB5010),有 LCD、6 顆旋鈕、MIL 按鈕和 USB 埠。手冊整理成下表:

項目內容
協定ISO15765-4(CAN)11-bit/29-bit × 250K/500K,另有 ISO9141-2、ISO14230 KWP(K-Line),用左下 4 位 DIP 開關切換,LCD 第一行會顯示目前協定
OBD 母座6 CAN-H、14 CAN-L、4/5 地、16 電源(附 13 V 變壓器)
6 顆旋鈕MAF(PID 10)、水溫(05)、轉速(0C)、車速(0D)、進氣溫度(0F)、節氣門(11)
MIL 按鈕按下去 MIL 亮、產生已存/待確認/永久故障碼和凍結資料
USBCP2102,115200 8N1,可以用指令改 PID 值、VIN 等
支援服務Mode 01、02、03、04、06、07、09、0A

PCAN 只能接 CAN 那四種,K-Line 收不到。手冊有一處前後矛盾:第 4 頁說旋鈕 1 是 PID 10(MAF),第 11 頁的 PID 表卻把「Knob 1」標在 PID 54(蒸發系統蒸氣壓)。實機轉旋鈕 1,變的是 MAF,PID 54 不動,所以第 11 頁是錯的。

ATS 的 OBD-II 掃描視窗怎麼做

ATS 的 CAN 視窗工具列多了一顆「OBD」,按下去開獨立視窗。流程是標準的 OBD-II(SAE J1979、ISO 15765-4):

  1. 先問 Mode 01 的 PID 00、20、40…「支援表」,每張表 4 bytes、32 個位元對應 32 個 PID,列出這台 ECU 支援哪些。
  2. 依序問支援的 PID,一問一答:送出請求後等到回應或逾時,才問下一個。
  3. 依 J1979 公式換算,例如轉速=(A×256+B)÷4、水溫=A−40、節氣門=A×100÷255。
  4. 按鈕讀 VIN(Mode 09)、故障碼(Mode 03 已存、07 待確認、0A 永久)、清除故障碼(Mode 04)。VIN 超過一框,要照 ISO-TP 回 Flow Control 才收得到後面幾框。
請求(功能定址 7DF):02 01 0D 55 55 55 55 55   ← 問 PID 0D 車速
回應(引擎 ECU 7E8):03 41 0D 3C ...            ← 0x3C = 60 km/h

實測(msi 筆電、PCAN-USB FD 用 Classic 500k、11-bit 功能定址):模擬器支援 93 個 PID(01~5F 幾乎都有),回應延遲約 31 ms(最大 62 ms),每秒約 20 問,0 逾時。輪詢一秒幾十框,預設不顯示在 CAN 視窗也不記 log,免得洗版;要留紀錄可以勾選打開。

踩到的坑

1. 讀得到值,兩秒後連線就自己斷了

ATS 原本的保護是「錯誤框持續 2 秒就自動中斷連線」,避免沒有 ACK 時控制器無限重送洗版。但 log 一看:這些 PCAN「錯誤框」的 ID 都是 0(沒有錯誤種類),而且接收錯誤計數一路往下掉(90 → 76 → 56)。PCAN 每成功收一框、計數減 1,就報一次狀態,34 次減少剛好對上那 35 個「錯誤框」。也就是說通訊正常、正在恢復,卻被當成錯誤。

修法:錯誤計數比上一次真的下降時,只當狀態顯示(每 5 秒最多一行),不算錯誤。計數上升或卡在同一個值,照舊重開通道、自動中斷。卡在同一個值這點很重要:真的錯誤很多時,計數會飽和在固定值,只用「沒有變大」來判斷會漏掉。我用假的錯誤框重播了四種情況驗證。一開始接收錯誤計數就有 90~127 的原因還沒查清,可能和終端電阻或共地有關。

2. 93 個 PID 輪流問,轉旋鈕要等 4~5 秒才看得到

一秒 20 問、93 個 PID 輪一圈要 4~5 秒,轉旋鈕時儀表要好幾秒才變。改成儀表上的 8 個 PID(6 顆旋鈕加負載、電壓)每一輪都問,其他 PID 每輪只插一個輪流,儀表大約每秒更新 2 次。

3. 轉旋鈕時 CAN 視窗沒有封包

OBD 是一問一答,模擬器不會因為旋鈕轉了就主動送東西,要等 ATS 問到那個 PID 才回。加上輪詢預設不顯示,CAN 視窗看起來就是空的。要看請求和回應一來一回,就勾「輪詢的框也顯示在 CAN 視窗」。

用 USB 指令改數值

旋鈕要用手轉,自動化測試不方便。模擬器的 USB 序列埠可以直接設 PID 值,指令以 | 結尾,成功回 OK>。在 ATS 裡用 UART 連那個 COM 埠,送 $PID0D:60|,OBD 視窗的車速就變成 60 km/h。我也把這些指令做成 ATS 的指令集(IMSB5010),可以點選或寫進腳本。模擬器也會從同一個埠印出它收到和回應的 OBD 封包,方便對照。

$PID0D:60|          車速 60 km/h
$PID0C:2000|        轉速 2000 rpm
$PID31:125|         清碼後行駛距離 125 km
$VINLFV3B28R8A3025310|   改 VIN(17 字)
<R>:<S>:[000007DF] 02 01 0D        ← 模擬器印出:收到請求
<T>:<S>:[000007E8] 03 41 0D 3C     ← 模擬器印出:回 60 km/h

還沒確認的是:用指令設了車速之後,再轉車速旋鈕會不會把它蓋掉。

把車速餵給車機(Geotab IOX)

車機走的是 Geotab 的 IO Expander 協定:GO 裝置是主控,車機(IOX)是從端,29-bit ID、500k。IOX 用 0x25 Type 2 跟 GO 要「GO 資料」,GO 回 0x27 Type 2,52 bytes 裡有時間、經緯度、車速(km/h)、轉速、里程(0.1 km)、狀態旗標(點火、匯流排有活動、車速/里程來自引擎…)、引擎時數等。ATS 本來就能模擬 GO,只是車速、轉速、里程是寫死的固定值。

這次在 IOX 視窗加了「車輛資料」:

  • 來源:可以選固定值,或任一條正在 OBD 掃描的 CAN 連線。也可以選偵測到、還沒連線的第二支 PCAN,ATS 會自動用同樣鮑率連上並開始掃描。
  • 選 OBD 時,車速(0D)、轉速(0C)、里程、引擎時數(1F 運轉秒數換算)都用 5 秒內的即時值,並設「車速/里程來自引擎」旗標。模擬器沒有里程 PID(A6),先用 PID 31(清碼後行駛距離)代替,可以用 $PID31:…| 設。
  • 同一支 PCAN 也行:OBD 用 11-bit、IOX 用 29-bit,模擬器和車機可以並在同一條 500k 匯流排上,ATS 同一條連線兩個功能一起跑。
  • 畫面上顯示車機來要過幾次、上次送了什麼,另外有「主動送一次」和「定時主動送」。

為什麼要「主動送」?翻了前一天的實機 log,車機只在每次 Linux 開機完成、報上 External Device ID 之後,跟 GO 要 1 次 GO 資料,之後就不再要了(一天 7 次,全部都是開機當下)。它每 10 秒送一次 protobuf,但對照 Geotab 官方的 iox_messaging.proto,最外層欄位編號對不上,不是標準的訂閱訊息,所以也不是在訂閱車速。照標準流程,車機只會拿到開機那一刻的車速;要即時車速只能由 GO 主動送,但這不在規格裡,車機收不收要實測。

藍牙篇:用 ELM327 讀 OBD

PCAN 要接線,有時候只想插上去就讀。手邊這顆是常見的 ELM327 藍牙 OBD 轉接頭,直接插在模擬器的 OBD 座上,從 OBD 座的 16 腳拿電。它用 ELM327 的 AT 指令集:電腦送文字 010D,它回一行一行的十六進位,最後以 > 提示字元結束;底層的 CAN、K-Line 協定和多框的 Flow Control 都由它自己處理。

Windows 配對與 COM 埠

  1. ELM327 插上 OBD 座(模擬器要開著)。
  2. Windows 設定 → 藍牙與裝置 → 新增裝置 → 藍牙,選 OBDII,PIN 碼 1234。
  3. 配對後 Windows 會多出兩個「透過藍牙連結的標準序列」COM 埠:一個外送(電腦主動連 ELM327)、一個內送。要用外送的那個:它的裝置執行個體路徑裡有 ELM327 的藍牙 MAC,內送的那個是一串 0。這台 msi 上外送是 COM47、內送是 COM46。這顆是傳統藍牙 SPP(不是 BLE),所以會有 COM 埠。

ATS 怎麼用 ELM327

在 ATS 用 UART 開外送的 COM 埠(藍牙序列埠不看鮑率,填 38400 就好),工具列一樣有「OBD」,開出來是同一個掃描視窗,只是設定區換成 ELM327 的協定選單(自動、CAN 11/29-bit、250k/500k、ISO 9141、KWP)。開始時 ATS 依序送:

ATZ      重置,回版本(例如 ELM327 v1.5)
ATE0     關回顯
ATL0     不要換行,只用 CR
ATS1     hex 之間加空白
ATH1     顯示表頭:每行變成 "7E8 03 41 0D 3C"
ATAT1    自動調整等待時間
ATSP0    協定自動
0100     第一次會 SEARCHING… 找協定,先用長逾時問一次
ATRV     OBD 座電壓
ATDPN    找到的協定(A6=自動找到 CAN 11-bit 500k)

重點是 ATH1:開表頭之後,CAN 回應每一行就是「回應 ID+原始 CAN 資料」,ATS 直接把它當成 CAN 框,餵給 PCAN 那條路已經寫好的解析(支援表、J1979 換算、VIN 多框、故障碼),兩種介面共用同一套程式。差別是 ELM327 一問一答要經過藍牙,比 PCAN 慢;但不用接線,而且 K-Line 的車它也讀得到。

實機結果:這顆回報是 ELM327 v2.1(市面上很多是仿製版),OBD 座電壓 12.3 V,用 CAN 11-bit 500k 讀到 ECU 7E8、93 個 PID,跟 PCAN 讀到的一致。

坑 1:自動找協定會把它弄當

第一次用 ATSP0(自動),ATZ 有回,但送 0100 讓它搜尋協定之後 12 秒都沒回應,接著藍牙連線整個斷掉,連寫入都卡住(Windows 的藍牙 COM 埠斷線時,寫入會一直等)。把連線關掉重開、改成直接指定 ATSP6(CAN 11-bit 500k)就正常了。所以 ATS 的「自動」現在不交給 ELM327 搜尋,而是自己依序試 CAN 11-bit 500k → 250k → 29-bit 500k → 250k,都不通才用 ATSP0;寫入也加了 2 秒逾時,藍牙斷了會提示重開連線,不會整個卡住。

坑 2:拔掉重插,連不回去(錯誤 121)

ELM327 從 OBD 座拔起來再插回去,在 ATS 按「連線」出現 OSError(22, '信號等待逾時。', None, 121)。原因是傳統藍牙 SPP 的 COM 埠不會自己連回去,而是「程式打開 COM 埠的那一刻」Windows 才去連 ELM327;轉接頭剛插上還在開機、或 Windows 還留著上一次的連線狀態時,這一次就會逾時。隔幾秒再開就好(從遠端再試一次,6.9 秒連上,ATI 回 ELM327 v2.1)。

所以 ATS 開 COM 埠時,遇到錯誤 121 就自動重試(最多 4 次、間隔 2 秒),其他錯誤(例如 COM 埠不存在)照舊直接顯示;4 次都不行才提示到 Windows 藍牙設定移除裝置、重新配對。改完實測:重插後直接按「連線」,大約 5 秒連上,接著初始化、找協定、讀到 93 個 PID 都正常。

坑 3:PCAN 和 ELM327 同時讀,兩邊一直逾時

PCAN 和 ELM327 接在同一條匯流排、兩個 OBD 視窗一起開,兩邊都開始出現「逾時」,ELM327 掉到每秒 0.8 問,水溫、MAF、進氣溫度一直讀不到;PCAN 那邊轉速、負載也逾時。

原因在 OBD 本身:ECU 的回應(7E8)沒有寫是回給誰的。兩個診斷工具都用功能定址 7DF 發問,ECU 一律從 7E8 回答,誰都分不出哪一則是自己的:

  • ELM327 這邊:它開了自動調整等待時間(ATAT1),收到第一個 7E8 就結束這次請求。PCAN 剛好問了轉速(010C),ECU 回的 41 0C … 就被正在問水溫(0105)的 ELM327 拿走——PID 對不上,等於沒有回應。
  • PCAN 這邊:兩邊的請求疊在一起時,模擬器(一顆單晶片)來不及處理,有些就漏回了。

這在真車上也一樣:同一條匯流排上同時掛兩個診斷工具會互搶回應。好在這兩個視窗都在同一個 ATS 裡,可以協調:

  1. 共用一把「匯流排鎖」:同一個 ATS 裡所有 OBD 掃描,一次只有一個請求在等回應,回應自然就是問的那一方的。一開始用一般的鎖,ELM327 放開後馬上又自己搶回來,PCAN 一直排不到(模擬測試 85 比 4.6 問/秒),所以改成先到先拿(排號碼牌)。
  2. 處理「晚到的回應」:PCAN 的請求等 150 ms 沒回就算逾時,但 ECU 有時候晚一點還是回了,這則晚到的 7E8 會被下一個發問的 ELM327 撿到。實測就遇到:先開 PCAN、再開 ELM327,ELM327 掃描第一問(支援表 PID 00)就被搶走,整個掃描停掉。所以支援表那一問改成沒回應先重試 3 次;ELM327 收到的回應如果不是它問的 PID,就再問一次。

為了在模擬環境重現,也把模擬的 ECU 改成回應要 5~15 ms、模擬的 ELM327 收到第一個回應就結束(跟真的一樣)。修之前模擬:ELM327 1283 問裡 1136 次逾時;修之後兩邊都 0 逾時。

情況ELM327PCAN
各自單獨跑約 9 問/秒,延遲約 110 ms約 22 問/秒,延遲約 15 ms
同時跑(修之前)0.4~0.8 問/秒,2579 問裡 1169 次逾時22 問/秒,43276 問裡 809 次逾時
同時跑(修之後)7.3 問/秒,469 問 2 次逾時7 問/秒,685 問 1 次逾時

同時跑時兩邊都只剩每秒 7 問左右,是因為要輪流用同一條匯流排;只開一個時速度不受影響。這把鎖只管得到同一個 ATS 裡的掃描,如果是別的程式(例如手機 App 透過同一顆 ELM327 或另一顆轉接頭)一起問,還是會搶。

ELM327 和 PCAN 怎麼選

ELM327 藍牙PCAN
接線插上 OBD 座就好,從 16 腳拿電要接 CAN-H/CAN-L、注意終端電阻
速度約 9 問/秒(藍牙+轉接頭處理)約 22 問/秒
協定CAN 和 K-Line(ISO 9141、KWP)都可以只有 CAN
看得到什麼只看得到回應匯流排上所有框(包括別人的請求)
注意仿製版自動找協定會卡、重插要幾秒才連得上錯誤計數、FD 設定

目前進度與下一步

  • ✔ OBD 視窗實機可用:93 個 PID、即時儀表、VIN、故障碼。
  • ✔ 旋鈕對應確認,手冊第 11 頁勘誤。
  • ✔ USB 指令改車速,OBD 讀得到。
  • ✔ PCAN 錯誤計數誤判斷線已修。
  • ✔ 車速可以當 GO 資料送給車機,同一支或兩支 PCAN 都行(模擬環境測過)。
  • ☐ 車機實機收不收「主動送」的車速、收到後在哪裡看得到。
  • ☐ USB 設的值會不會被旋鈕蓋掉;永久故障碼清不清得掉。
  • ☐ 一開始接收錯誤計數偏高的原因(終端電阻、共地)。
  • ✔ 藍牙 ELM327 實機在 ATS 上讀 OBD:v2.1、93 個 PID(仿製版的自動協定搜尋會卡死,改成 ATS 自己依序試)。
  • ✔ ELM327 重插自動重連(錯誤 121 重試,約 5 秒);PCAN 和 ELM327 同時讀不互搶(共用匯流排鎖,各約 7 問/秒)。

延伸閱讀:車內 ECU 圖鑑:模組種類、車內網路,以及用 PCAN+UDS 在測試台上找出有哪些 ECU(OBD-II 之外,用 UDS 盤點一整座測試台上的模組)。

沒有留言:

張貼留言