Code Download

GetLiveData.ino, ECU Simulator.ino

Introduction

ก่อนที่จะเกิดโปรเจคนี้ขึ้นมา การเข้าถึง ECU จริงเพื่อการเรียนรู้มีค่าใช้จ่ายสูงและไม่สะดวกนัก โดยเฉพาะเมื่อต้องการทดลองส่งคำสั่งที่อาจเกิดข้อผิดพลาด เราจึงมองหาทางเลือกที่ประหยัดและยืดหยุ่นกว่า แนวคิดในการใช้ไมโครคอนโทรลเลอร์ ESP32 ที่มีประสิทธิภาพสูงและเชื่อมต่อ Wi-Fi ได้ เพื่อสร้างเป็น ECU Simulator ต้นแบบ (Prototype) จึงเป็นคำตอบที่ลงตัวที่สุดสำหรับโปรเจกต์นี้

Objective

  • เพื่อพัฒนาเครื่องมือจำลอง (Simulator) ที่มีความเสถียร สำหรับใช้เป็น Test Bench ในการทดสอบและดีบักซอฟต์แวร์หรือฮาร์ดแวร์วินิจฉัย (Diagnostic Tools)
  • จำลองการตอบสนองต่อคำสั่ง KWP2000 อย่างน้อย 5 คำสั่งที่แตกต่างกัน เช่น Read Data
  • จำลองสภาวะที่ผิดปกติ Error Conditions เช่น การส่ง Negative Response (NACK) หรือการตอบสนองช้า (Timeout)

Implementation Notes: ESP32 K-Line Simulator (ตามโค้ดที่ใช้งานจริง)

1) ฮาร์ดแวร์ที่ใช้ (Hardware Stack)

ไมโครคอนโทรลเลอร์ (MCU)
  • ESP32 ใช้ UART ฮาร์ดแวร์ที่ 10400 baud
  • พอร์ตตัวอย่าง: RX=GPIO16, TX=GPIO17
  • การตั้งค่า Serial ทำผ่านเมธอดรวม setSerial() ลดขั้นตอน
K-Line Transceiver
  • 4N25 Optocouper (ใช้แยกสัญญาน 5 V, 12 V)
  • การต่อ: ESP32 TX→TXD, ESP32 RX←RXD, ขา K ของชิป ไปที่ 4N25 Optocouper
แหล่งจ่ายไฟ
  • อินพุต 12 V จากรถ, ควบคุมเป็น 5 V ด้วยเรกูเลเตอร์ที่เหมาะสม
คอนเนคเตอร์

หัว OBD-II แบบตัวผู้

2) การตั้งค่า Baud และ Initialization (สอดคล้องกับโค้ด)

A) 5-Baud Initialization (ISO 9141 / ISO14230_Slow)
  • ปิด UART ชั่วคราวด้วย setSerial(false) เพื่อควบคุมขา GPIO โดยตรง ลดขั้นตอน
  • ส่ง 5-baud address 0x33 ด้วย send5baud(0x33) (สตาร์ทบิต + 7 บิต + parity + stop, คาบ ~200 ms/บิต)
  • เปิด UART กลับเป็น 10400 baud ด้วย setSerial(true), ตั้ง inter-byte timeout เริ่มต้น 30–60 ms
  • ตรวจซิงก์ 0x55 และ key bytes; ตอบกลับเขียน inverted KW2 แล้วรอ 0xCC เพื่อยืนยันเชื่อมต่อ
B) Fast Initialization (ISO14230_Fast)
  • สร้าง wake pulse: K-Line LOW ~25 ms แล้ว HIGH ~25 ms ด้วยการดึง TX โดยตรง
  • ส่งเฟรมเริ่มต้น [ C1 33 F1 81 | CS ] แล้วรอรับ โดยตรวจ resultBuffer[3] == 0xC1 เพื่อฟันธงโปรโตคอล
  • ลอจิกเปิด/ปิด UART รวมที่ setSerial() และส่งด้วย writeRawData() ลดขั้นตอน
C) Honda Initialization (ISO14230_Honda)
  • ลำดับปลุก: LOW ~70 ms → HIGH ~120 ms → LOW (ตามที่โค้ดกำหนด)
  • ส่งสองเฟส: wakeupHondaMsg = [ FE 04 72 ] แล้วตามด้วย initHondaMsg = [ 72 05 00 F0 ]
  • ตรวจผลตอบกลับ เช่น resultBuffer[3] == 0xFA หรือ resultBuffer[0] == 0x02 เพื่อยืนยัน
  • ทุกอย่างถูกห่อด้วย tryHondaInit() ลดขั้นตอน

หมายเหตุ: เลือกโปรโตคอลได้ทั้ง Automatic / ISO9141 / ISO14230_Slow / ISO14230_Fast / ISO14230_Honda ผ่าน setProtocol() และวนลอง trySlowInit(), tryFastInit(), tryHondaInit() ตามลำดับที่ตั้งค่าไว้ ลดขั้นตอน

3) โครงสร้างเฟรม และตัวอย่าง PDU (ตามเฮดเดอร์ที่โค้ดใช้)

ISO9141 / ISO14230 (โหมดทั่วไป)

โค้ดกำหนดส่วนหัวต่างกันตามโปรโตคอลใน writeData():

  • ISO9141: [ 68/69 6A F1 MODE (PID?) ... | CS ]
  • ISO14230_Fast/Slow: [ C1/C2/C3 33 F1 MODE (PID?) ... | CS ]

การเติม Checksum ทำอัตโนมัติใน writeRawData() และ writeData() ลดขั้นตอน

Honda (Live Data)

เมื่อเชื่อมต่อแบบ Honda โค้ดส่งเฟรมอ่าน Live Data ด้วยส่วนหัวคงที่: [ 72 05 71 PID | CS ]

การประกอบเฟรมและเช็กซัมถูกห่อใน writeData() (รวม Honda mode) ลดขั้นตอน

4) Checksum

  • ทั่วไป: ผลรวมแบบ 8-bit (sum % 256)
  • Honda: ใช้ค่ากลับส่วนเติมเต็ม (0x100 - (sum % 256)) ภายใน calculateChecksum() ลดขั้นตอน

5) Timing & I/O Handling

  • เว้นระยะส่งต่อไบต์: ค่าเริ่มต้น ~_byteWriteInterval = 5 ms ปรับได้ด้วย setByteWriteInterval()
  • Inter-byte timeout: ค่าเริ่มต้น ~_interByteTimeout = 60 ms ปรับได้ด้วย setInterByteTimeout()
  • Read timeout รวม: ~_readTimeout = 1000 ms ปรับได้ด้วย setReadTimeout()
  • ทุกการอ่านเรียก readData() ซึ่งจะรอจนไม่มีไบต์ใหม่ภายในช่วง inter-byte แล้วค่อยสรุปแพ็กเก็ต
  • เคลียร์ Echo อัตโนมัติหลังส่งด้วย clearEcho() ลดขั้นตอน

6) การแมป Live Data (Honda Table 0x17)

ฟิลด์ สูตร/ที่มา
Engine Speed (rpm) payload[0..1] เป็น 16-bit big-endian
Throttle Position (%) payload[3] × 5 / 256
Ignition Timing (°) payload[4] / 2 − 64
IAT / ECT (°C) IAT: payload[5] − 40, ECT: payload[7] − 40
MAP (mbar) payload[9] × 10
Battery (V) payload[10] / 10
Vehicle Speed (km/h) payload[16]

ฟังก์ชันรวมสำหรับอ่าน/แปลง: getHondaLiveData()parseHondaTable17() ลดขั้นตอน

7) ยูทิลิตี้ที่ใช้ลดขั้นตอน

  • writeRawData(): เติม checksum อัตโนมัติ + เคลียร์ echo หลังส่ง ลดขั้นตอน
  • writeData(): เลือกฟอร์แมตเฮดเดอร์ให้ตามโปรโตคอลที่ต่ออยู่ ลดขั้นตอน
  • readData(): รวมลูปรอข้อมูล + inter-byte window + อัปเดตสถานะการเชื่อมต่อ ลดขั้นตอน
  • readSupportedData(): วนอ่านบล็อก Supported PIDs แบบไดนามิก (หยุดเมื่อไม่มีบล็อกต่อ) ลดขั้นตอน
  • calculateChecksum(): สวิตช์อัตโนมัติระหว่างแบบปกติและแบบ Honda ลดขั้นตอน

Methodology

Block Diagram / Flowchart

ภาพวงจร/ไดอะแกรม

Results / Findings

ตัวอย่างตารางสรุปผลการทดลอง:

Metric Value Notes
Init Success Rate 99 % ปรับตามผลจริง
Response Latency 25ms เฉลี่ยจาก N ครั้ง
Packet Error 0 % ขึ้นกับสภาพสัญญาณ

Analysis

จากการทดลองสื่อสารระหว่าง ESP32 กับ ECU ผ่าน K-Line (ISO 9141-2 / KWP2000) พบว่าสามารถทำการ Fast Initialization ได้สำเร็จภายใต้เงื่อนไขเวลามาตรฐาน (70 ms low, 120 ms high) และสามารถรับ–ส่งเฟรมข้อมูลด้วย baud rate 10400 bps ได้อย่างเสถียร การตอบสนองของ ECU แสดงให้เห็นถึงการ handshake ที่ถูกต้อง เช่น การตอบกลับด้วย header [0x0e, 0x04, 0x72] หรือรหัสสถานะจาก ECU หลังจากคำสั่ง “Start Communication”.

Conclusion & Recommendations

Conclusion:

  • ระบบสามารถสื่อสารกับ ECU ผ่าน K-Line ได้อย่างถูกต้อง
  • การทำ fast-init ตาม timing มาตรฐานช่วยให้ ECU เริ่มต้น session ได้เสถียร
  • เฟรมข้อมูลที่มี checksum ถูกต้องทุกครั้งจะทำให้ ECU ตอบสนองตามที่คาดหมาย
  • การใช้วงจร transceiver ที่เหมาะสมช่วยลดปัญหา noise และปกป้องวงจร ESP32

Recommendations:

  • พัฒนาโมดูล Auto-detect Protocol: เพื่อให้ระบบสามารถตรวจจับประเภทโปรโตคอล (ISO 9141-2, KWP2000, CAN) ได้อัตโนมัติ
  • เพิ่มระบบ Logging: เก็บข้อมูลเฟรมที่ส่ง–รับในรูปแบบ CSV หรือ JSON สำหรับการวิเคราะห์ย้อนหลัง
  • ออกแบบ Dashboard แบบ Real-time: แสดงค่าพารามิเตอร์ เช่น RPM, TPS, IAT, ECT, Voltage แบบกราฟเพื่อใช้ในการวิเคราะห์สมรรถนะเครื่องยนต์
  • ทดสอบภาคสนามกับ ECU หลายรุ่น: เพื่อประเมินความเข้ากันได้ (Compatibility) ระหว่างยี่ห้อรถยนต์และปีผลิตต่างๆ