📺 影片版(約 6 分鐘):想先看實際操作的話可以直接看這支影片,完整步驟、設定與程式碼在下方文字版。
YouTube:https://youtu.be/ogyptBIosK4(winson-DIY 頻道)
在這一篇文章中PeakCAN Bus 與 ECU Simulator 通訊 擷取 DTC Data
得到DTC錯誤代碼但是有太多的錯誤代碼, 本來想說在本機建立一個database來搜尋, 靈機一動想說現在萬物都OpenAI, 於是就在得到DTC時把OpenAI API的功能寫進去來尋找 DTC的意義!
錯誤碼=>所有常見的 OBD2 錯誤代碼:解讀 P、B、C、U 程式碼private async void button3_Click(object sender, EventArgs e)
{
//string dtcCode = txtDTC.Text.Trim();
string dtcCode = "P0218".Trim();
if (string.IsNullOrEmpty(dtcCode))
{
MessageBox.Show("請輸入 DTC 代碼,例如 P0202");
return;
}
button3.Enabled = false;
//txtResult.Text = "查詢中,請稍候...";
CommonData.WriteMessage("查詢中,請稍候...", "", Color.Blue, Color.Red);
string myApiKey = "your key";
ChatClient client = new(
model: "gpt-4.1", //gpt-4
apiKey: myApiKey
);
try
{
var prompt = $"請解釋 OBD2 故障碼 {dtcCode} 的意思,用繁體中文回答";
ChatCompletion completion = await client.CompleteChatAsync(prompt);
CommonData.WriteMessage("查詢結果...", completion.Content[0].Text.ToString(), Color.Blue, Color.Red);
}
catch (Exception ex)
{
//txtResult.Text = "錯誤:" + ex.Message;
}
finally
{
button3.Enabled = true;
}
}
還真的可以用!真是方便!!
補充(2026/10 更新):AI 解釋 DTC 會不會講錯?實測與改良做法
這篇是去年 8 月第一次把 OpenAI 接進 PeakCAN 程式時寫的,當時覺得「還真的可以用」。後來想把它改成不用付費、可以離線的版本,就在 GX10 本機用 Ollama 跑同一句提示詞,結果發現一個很重要的問題:AI 會很有自信地講錯故障碼的意思。這段補充整理實測結果,以及比較可靠的改良做法。
補充一、整個流程回顧
PeakCAN(PCAN-USB)──CAN 500 kbit/s──▶ ECU Simulator 1. 送 Mode 03 讀取 DTC:ID 0x7DF,資料 01 03 00 00 00 00 00 00 2. 收到 First Frame:ID 0x7E8,10 10 43 02 01 68 03 03 3. 回 Flow Control:ID 0x7E0,30 00 00 00 00 00 00 00 4. 解碼:01 68 → P0168、03 03 → P0303 5. 把故障碼送給 AI,取得中文解釋,顯示在下方訊息區第 1~4 步的細節在前一篇:PeakCAN 與 ECU Simulator 通訊 擷取 DTC Data。這篇補充的重點在第 5 步。
補充二、實測:本機模型會把故障碼講錯
用跟文章 C# 程式完全相同的提示詞「請解釋 OBD2 故障碼 {代碼} 的意思,用繁體中文回答」,在 GX10 上用 Ollama 問兩個本機模型,結果如下:
| 故障碼 | SAE 標準定義 | gemma4:12b 的回答 | qwen3.6:35b 的回答 |
|---|---|---|---|
| P0168 | Fuel Temperature Too High(燃油溫度過高) | ❌ 燃燒過稀 Bank 1(這其實是 P0171) | ❌ 第三列氧感測器電路異常 |
| P0303 | Cylinder 3 Misfire Detected(第 3 缸失火) | ✔ 正確 | ✔ 正確 |
| P0218 | Transmission Fluid Over Temperature Condition(變速箱油溫過高) | ❌ 冷卻液溫度感測器電路 | ❌ 怠速時冷卻液溫度偏高 |
三個故障碼錯了兩個,而且錯的答案寫得非常完整,有原因、有症狀、有維修建議,看起來就像真的一樣。如果沒有對照標準定義,很容易就相信了。
文章截圖裡雲端的 gpt-4.1 這三個都答對了(P0218 變速箱溫度過高、P0168 燃油溫度過高、P0303 第 3 缸失火),大模型對常見的 P 碼確實比較準。但「這次答對」不代表每次都對,尤其是車廠自訂的 P1xxx、U 碼這類比較冷門的故障碼,大模型一樣可能亂講。
補充三、改良做法:先查表,AI 只負責解釋
一開始「本來想在本機建一個 database 來搜尋」的想法其實是對的,只是不用二選一,兩個一起用:
- 標準定義從本地 DTC 表查:SAE J2012 的通用碼(P0xxx、C0xxx、B0xxx、U0xxx)定義是固定的,存成一個 CSV 或字典就好
- 把查到的定義放進提示詞,請 AI「只根據這個定義」用中文說明代表什麼、常見原因
- 表裡查不到的碼不送 AI,直接顯示「未知代碼,請查原廠手冊」,不讓 AI 自己猜
提示詞:OBD2 故障碼 P0168 的 SAE 標準定義是「Fuel Temperature Too High」。
請只根據這個定義,用繁體中文、三句話以內說明它代表什麼,
以及最常見的兩個原因。不要更改定義。
P0168 → 引擎偵測到燃油溫度過高。最常見的兩個原因是燃油溫度傳感器故障或燃料相關系統過熱。 ✔
P0303 → 引擎偵測到第三缸發生失火……最常見的兩個原因是火星塞或點火線圈損壞。 ✔
P0218 → 變速箱油溫過高……最常見的兩個原因是變速箱油量不足,以及內部磨損導致摩擦過熱。 ✔
P1234 → 本地表查不到,不送 AI ✔
三個全部正確,連小模型也不會再講錯。另外,要求「三句話以內」也讓回答從 1,400~1,900 個 token 降到幾十個字,訊息區比較好讀,用雲端 API 時費用也跟著降下來。補充四、C# 程式改良版
原本的程式有幾個地方可以改:
- 故障碼寫死成
"P0218",實際要用解碼出來的結果;而且 ECU 一次可能回好幾個碼(畫面上的P0168P0303),要拆開逐一查 - API 金鑰直接寫在程式裡,改成讀環境變數,程式碼才不會不小心把金鑰一起分享出去
catch區塊是空的,出錯時畫面上什麼都不會顯示,至少要把錯誤訊息印出來
static List<string> DecodeDtcs(byte[] data, int count)
{
char[] type = { 'P', 'C', 'B', 'U' };
var list = new List<string>();
for (int i = 0; i < count; i++)
{
byte b1 = data[i * 2], b2 = data[i * 2 + 1];
if (b1 == 0 && b2 == 0) continue; // 00 00 是填充,不是故障碼
list.Add($"{type[b1 >> 6]}{(b1 >> 4) & 0x3}{b1 & 0xF:X}{b2:X2}");
}
return list; // 01 68 03 03 → P0168, P0303
}
2. 先查表、再問 AI:static readonly Dictionary<string, string> DtcTable = new()
{
["P0168"] = "Fuel Temperature Too High",
["P0303"] = "Cylinder 3 Misfire Detected",
["P0218"] = "Transmission Fluid Over Temperature Condition",
// ……其餘從 CSV 載入
};
async Task<string> ExplainDtcAsync(ChatClient client, string code)
{
if (!DtcTable.TryGetValue(code, out var name))
return $"{code}:本地表查不到,請查原廠維修手冊";
string prompt = $"OBD2 故障碼 {code} 的 SAE 標準定義是「{name}」。" +
"請只根據這個定義,用繁體中文、三句話以內說明它代表什麼," +
"以及最常見的兩個原因。不要更改定義。";
ChatCompletion c = await client.CompleteChatAsync(prompt);
return $"{code}({name}):{c.Content[0].Text}";
}
3. 雲端或本機二選一:OpenAI 的 NuGet 套件也能連 Ollama,因為 Ollama 提供相容 OpenAI 的 API,只要換掉 Endpoint:using System.ClientModel;
using OpenAI;
using OpenAI.Chat;
// 雲端 OpenAI:金鑰從環境變數讀
ChatClient cloud = new("gpt-4.1-mini",
Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
// 本機 Ollama(GX10):金鑰隨便填,不會檢查
ChatClient local = new("gemma4:12b",
new ApiKeyCredential("ollama"),
new OpenAIClientOptions { Endpoint = new Uri("http://GX10的IP:11434/v1") });
注意:Ollama 預設只聽 127.0.0.1,Windows 測試機要連 GX10 的話,要在 GX10 設 OLLAMA_HOST=0.0.0.0,而且建議走 Tailscale,不要把 11434 埠直接開到公司或家裡的整個網段。補充五、雲端 OpenAI 與本機 Ollama 怎麼選
| 雲端 OpenAI(gpt-4.1 / mini) | 本機 Ollama(GX10) | |
|---|---|---|
| 費用 | 按 token 計費 | 免費 |
| 網路 | 要能連外網 | 產線、實驗室內網也能用 |
| 速度 | 通常幾秒 | 這次實測 gemma4:12b 一個碼約 20~70 秒 |
| 不查表直接問 | 常見碼大多正確 | 實測 3 個錯 2 個,不建議 |
| 先查表再問 | 正確 | 實測 3 個全對 |
結論:不管用雲端還是本機,都建議「先查表、AI 只負責解釋」。這樣小模型就夠用,也不用擔心 AI 編出一個看起來很專業、其實是錯的答案。
延伸閱讀



沒有留言:
張貼留言