Giới thiệu dự án
Bối cảnh ngành và thực trạng kỹ thuật
Sự chuyển dịch toàn cầu sang các phương tiện giao thông thuần điện (Electric Vehicles - EV) và xe máy điện hai bánh (Light Electric Vehicles - LEV) đang thúc đẩy việc tái cấu trúc toàn bộ kiến trúc điện lực - điện tử (E/E Architecture) trên phương tiện. Theo các báo cáo kỹ thuật ngành ô tô, một chiếc ô tô hiện đại tích hợp từ 30 đến hơn 100 hộp điều khiển điện tử (Electronic Control Unit - ECU), trong khi các dòng xe máy điện thông minh thế hệ mới cũng tích hợp từ 5 đến 12 ECU độc lập (bao gồm VCU - Vehicle Control Unit, BMS - Battery Management System, MCU - Motor Control Unit, Cluster, ABS).
+-------------------------------------------------------------------------+
| KIẾN TRÚC MẠNG TRUYỀN THỐNG VS MẠNG CAN |
+-------------------------------------------------------------------------+
| Point-to-Point (UART/Analog): Mạng Bus CAN vi sai (ISO 11898): |
| - Dây dẫn chằng chịt, cồng kềnh - Chỉ 2 dây xoắn (CAN_H & CAN_L) |
| - Dễ nhiễu EMI khoang động cơ - Miễn nhiễm nhiễu đồng pha (CMR) |
| - Khó mở rộng, bảo trì phức tạp - Cấu trúc đa chủ, dễ cắm/rút node|
+-------------------------------------------------------------------------+
Việc kết nối các cụm điều khiển và cảm biến theo phương thức nối dây trực tiếp (point-to-point hardwiring) hoặc giao tiếp điểm-điểm truyền thống (UART, RS-232) bộc lộ nhược điểm chí mạng:
- Làm tăng chiều dài và trọng lượng bó dây (wiring harness) lên tới 35-40%.
- Tăng chi phí lắp ráp và xác suất đứt ngầm mạch điện.
- Suy giảm chất lượng tín hiệu do nhiễu điện từ trường (Electromagnetic Interference - EMI) phát sinh từ bộ nghịch lưu (Inverter) và động cơ điện công suất lớn.
Vấn đề kỹ thuật cần giải quyết (Problem Statement)
Các hệ thống hiển thị thông số cụm táp-lô (Digital Instrument Cluster) trên các mẫu xe điện phân khúc phổ thông hiện nay vẫn gặp phải các điểm nghẽn kỹ thuật:
- Thiếu tính đồng bộ thời gian thực: Độ trễ hiển thị tốc độ, dung lượng pin (SOC) và nhiệt độ vượt quá 100ms khi dùng giao thức tuần tự thông thường, gây rủi ro an toàn cho người điều khiển.
- Suy hao và sai lệch dữ liệu do nhiễu EMI: Tín hiệu analog từ cảm biến tốc độ và dòng điện pin dễ bị biến dạng bởi xung đóng cắt tần số cao (PWM) của biến tần.
- Khả năng mở rộng node kém: Khi bổ sung các hệ thống an toàn mới (như phanh ABS, kiểm soát lực kéo TCS, cảm biến áp suất lốp TPMS), hệ thống hiển thị cũ phải thiết kế lại toàn bộ phần cứng bo mạch chủ.
Mục tiêu của đề tài
- Nghiên cứu chuyên sâu giao thức CAN (Controller Area Network): Làm chủ cơ chế truyền nhận vi sai, cấu trúc khung dữ liệu CAN 2.0A/2.0B theo tiêu chuẩn ISO 11898-2.
- Thiết kế phần cứng nút mạng CAN (CAN Nodes): Ứng dụng vi điều khiển ATmega328P (Arduino Uno R3) kết hợp bộ điều khiển CAN độc lập MCP2515 và bộ thu phát (Transceiver) TJA1050 qua giao tiếp SPI.
- Xây dựng thuật toán phân xử và đóng gói dữ liệu: Lập trình giả lập tín hiệu tốc độ xe (Speedometer), vòng tua động cơ điện (RPM), mức điện áp/dung lượng pin, nhiệt độ và trạng thái đèn tín hiệu thành các gói tin CAN chuẩn (Payload 8 bytes).
- Phát triển giao diện táp-lô kỹ thuật số (Digital Instrument Dashboard): Lập trình ứng dụng đồ họa bằng ngôn ngữ Python, tiếp nhận luồng dữ liệu từ CAN Bus qua Serial Bridge để hiển thị trực quan, mượt mà theo thời gian thực.
- Chế tạo mô hình thực nghiệm hoàn chỉnh: Gia công khung vỏ táp-lô mô phỏng bằng AutoCAD và đánh giá độ ổn định của hệ thống mạng 2 node.
Giải pháp kỹ thuật và cơ sở lý luận
Đề tài lựa chọn kiến trúc mạng CAN tốc độ cao (CAN High Speed, cấu hình ở tốc độ truyền 250 kbps - 500 kbps) sử dụng cặp dây xoắn vi sai CAN_H và CAN_L cùng hai điện trở đầu cuối $120\ \Omega$.
Cơ sở lựa chọn:
- Cơ chế phân xử không phá hủy (Non-Destructive Bitwise Arbitration) dựa trên ID định danh giúp các thông điệp khẩn cấp (như cảnh báo quá nhiệt, sự cố phanh) luôn được ưu tiên truyền trước mà không gây xung đột bus.
- Mã kiểm tra vòng CRC 15-bit (Cyclic Redundancy Check) kết hợp cơ chế kiểm tra khung bit (Bit Stuffing) đảm bảo tính toàn vẹn dữ liệu cực cao trong môi trường xe điện nhiều xung nhiễu.
- Tầng hiển thị phần mềm xây dựng bằng Python mang lại khả năng tùy biến giao diện đồ họa trực quan, dễ dàng tích hợp thuật toán xử lý dữ liệu và xuất dữ liệu ra màn hình.
Kết quả kỳ vọng và chỉ số định lượng
- Tốc độ truyền dữ liệu Bus: Đạt 250 kbps / 500 kbps, tần số cập nhật gói tin $\ge 50\text{ Hz}$ ($20\text{ ms/frame}$).
- Thời gian trễ truyền nhận từ nút cảm biến đến màn hình (End-to-End Latency): $\le 25\text{ ms}$.
- Tỷ lệ suy hao gói tin (Packet Loss Rate): $< 0.05%$ trong điều kiện hoạt động tiêu chuẩn.
- Tốc độ làm tươi giao diện Python (GUI Frame Rate): Đạt 30 - 60 FPS (Frames Per Second), đảm bảo kim đồng hồ và số đo điện tử không bị giật lag.
Phạm vi và giới hạn đề tài
- Phạm vi: Mô phỏng mạng CAN 2 node cục bộ (Node phát đóng vai trò ECU điều khiển/thu thập cảm biến; Node thu nhận đóng vai trò Gateway giao tiếp máy tính hiển thị táp-lô).
- Giới hạn: Sử dụng máy tính cá nhân làm màn hình hiển thị táp-lô thông qua cầu chuyển đổi UART-Serial từ Arduino; chưa tích hợp trực tiếp vi điều khiển CAN Native lên bo mạch LCD công nghiệp chuyên dụng.
Phân tích và thiết kế giải pháp
Phân tích hiện trạng và so sánh công nghệ
| Tiêu chí so sánh |
Hệ thống dây truyền thống (Hardwired) |
Giao tiếp Nối tiếp (UART / RS-485) |
Mạng LIN (Local Interconnect Network) |
Mạng CAN (ISO 11898) - Lựa chọn đề tài |
| Số lượng dây dẫn |
Rất nhiều (1 dây/tín hiệu, hàng chục sợi) |
2 - 4 dây |
1 dây đơn (Single Wire) |
2 dây xoắn vi sai (CAN_H, CAN_L) |
| Tốc độ truyền tối đa |
Tín hiệu điện áp trực tiếp |
115.2 kbps |
Tối đa 20 kbps |
125 kbps - 1 Mbps (CAN 2.0) |
| Khả năng chống nhiễu |
Kém (Dễ méo tín hiệu Analog) |
Trung bình (RS-485 khá, UART kém) |
Trung bình |
Rất cao (Nhờ điện áp vi sai $V_{\text{diff}}$) |
| Cơ chế phân xử xung đột |
Không áp dụng |
Dễ xảy ra tranh chấp nếu đa chủ |
Master-Slave (Không đa chủ) |
Phân xử không phá hủy theo mức bit Dominant |
| Chi phí triển khai |
Cao về gia công bó dây |
Thấp |
Rất thấp |
Hợp lý, tối ưu cho ô tô - xe điện |
| Ứng dụng điển hình |
Xe máy xăng đời cũ |
Giao tiếp vi điều khiển đơn giản |
Điều khiển gương, cửa, ghế, đèn phụ |
Hệ thống truyền lực, phanh, táp-lô, BMS, VCU |
Phân tích yêu cầu hệ thống theo mô hình MoSCoW
- Must Have (Bắt buộc phải có):
- Truyền nhận dữ liệu 8-byte qua CAN Bus giữa 2 vi điều khiển qua IC điều khiển MCP2515.
- Hiển thị vận tốc tức thời ($0 - 120\text{ km/h}$), mức pin ($0 - 100%$), nhiệt độ động cơ ($0 - 150^\circ\text{C}$).
- Hiển thị trạng thái đèn báo rẽ (Xi-nhan Trái/Phải), đèn pha chiếu xa (High Beam), đèn cảnh báo lỗi hệ thống.
- Cơ chế nhận diện và lọc gói tin thông qua Acceptance Filter và Mask.
- Should Have (Nên có):
- Màn hình phụ (Tablo phụ) hỗ trợ hiển thị đồ họa chi tiết và menu cài đặt thông số.
- Đồng hồ thời gian thực (RTC) hiển thị giờ vận hành.
- Báo lỗi tự động khi mất kết nối cáp vật lý CAN.
- Could Have (Có thể mở rộng):
- Tích hợp thêm cảm biến dòng điện Hall Effect thực tế và cảm biến nhiệt độ DS18B20.
- Xuất dữ liệu ra file log để phân tích hiệu suất tiêu thụ điện.
- Won't Have (Chưa thực hiện trong giai đoạn này):
- Kết nối không dây Telematics lên Cloud/Server IoT qua mạng 4G/5G.
- Tiêu chuẩn an toàn chức năng ISO 26262 ASIL-D.
Thiết kế kiến trúc hệ thống
+---------------------------------------------------------------------------------------------------+
| SƠ ĐỒ KIẾN TRÚC MẠNG VÀ PHẦN MỀM |
+---------------------------------------------------------------------------------------------------+
[Node 1: Bộ điều khiển / Cảm biến] [Node 2: Gateway Táp-lô]
+----------------------------------+ +----------------------------------+
| 3x Biến trở (Tốc độ, Pin, Nhiệt) | | MCU ATmega328P (Arduino Uno R3) |
| 4x Nút nhấn (Xi-nhan, Pha, Còi) | | SPI Interface (SCK, MOSI, MISO) |
| MCU ATmega328P (Arduino Uno R3) | +-----------------+----------------+
| SPI Interface (10 MHz) | | (SPI Bus)
+-----------------+----------------+ +-----------------+----------------+
| (SPI Bus) | MCP2515 CAN Controller |
+-----------------+----------------+ | TJA1050 Transceiver |
| MCP2515 CAN Controller | +-----------------+----------------+
| TJA1050 Transceiver | |
+-----------------+----------------+ | CAN_H / CAN_L
| | (Bus vi sai 120 Ohm)
+==================== CAN BUS =====================+
|
(USB/Serial Bridge)
v
+----------------------------------+
| Giao diện Python Desktop GUI |
| - Đồng hồ đo vận tốc (Analog) |
| - Thanh hiển thị pin & nhiệt độ |
| - Cụm đèn báo rẽ & cảnh báo lỗi |
+----------------------------------+
Thiết kế điện áp lớp vật lý (Physical Layer Voltage Levels)
Hệ thống sử dụng chuẩn CAN High Speed (ISO 11898-2) với đặc tính điện áp vi sai đo giữa hai dây CAN_H và CAN_L:
- Trạng thái lặn (Recessive bit - Logic 1): Cả $V_{\text{CAN_H}}$ và $V_{\text{CAN_L}}$ đều ở mức xấp xỉ $2.5\text{ V}$. Điện áp vi sai $V_{\text{diff}} = V_{\text{CAN_H}} - V_{\text{CAN_L}} \approx 0\text{ V}$.
- Trạng thái trội (Dominant bit - Logic 0): $V_{\text{CAN_H}}$ tăng lên $3.5\text{ V}$, $V_{\text{CAN_L}}$ giảm xuống $1.5\text{ V}$. Điện áp vi sai $V_{\text{diff}} = 3.5\text{ V} - 1.5\text{ V} = 2.0\text{ V}$.
Cấu trúc khung truyền dữ liệu CAN (CAN Data Frame Layout)
Hệ thống sử dụng định dạng khung tiêu chuẩn CAN 2.0A với 11-bit Identifier (ID):
| Vùng (Field) |
Độ dài |
Giá trị cấu hình |
Chức năng kỹ thuật |
| SOF (Start of Frame) |
1 bit |
Dominant (0) |
Báo hiệu khởi tạo frame, đồng bộ pha thời gian các node |
| Arbitration Field |
12 bit |
ID: 0x036 hoặc 0x042, RTR: 0 |
Định danh độ ưu tiên của gói tin (ID thấp hơn = ưu tiên cao hơn) |
| Control Field |
6 bit |
IDE: 0, r0: 0, DLC: 0b1000 (8) |
Báo chuẩn 2.0A và xác định kích thước Payload là 8 byte |
| Data Field (Payload) |
64 bit (8 bytes) |
Byte 0-7 chứa dữ liệu cảm biến |
Chi tiết phân bố byte dữ liệu điều khiển xe máy điện |
| CRC Field |
16 bit |
CRC-15 + 1 bit Delimiter |
Phát hiện lỗi bit với đa thức kiểm tra modulo-2 |
| ACK Field |
2 bit |
ACK Slot + ACK Delimiter |
Node nhận kéo Dominant để xác nhận frame hợp lệ |
| EOF (End of Frame) |
7 bit |
Recessive (1111111) |
Báo hiệu kết thúc gói tin CAN hoàn chỉnh |
Phân bổ 8 Byte Payload của Frame chính (ID 0x036):
Byte 0: Vận tốc tức thời ($0 - 120\text{ km/h}$, phân giải $1\text{ km/h/bit}$).
Byte 1: Dung lượng pin SOC ($0 - 100%$, phân giải $1%/\text{bit}$).
Byte 2: Nhiệt độ động cơ ($0 - 150^\circ\text{C}$, offset $0$).
Byte 3: Trạng thái đèn tín hiệu (Bit 0: Xi-nhan trái, Bit 1: Xi-nhan phải, Bit 2: Đèn Pha, Bit 3: Cảnh báo nguy hiểm).
Byte 4-5: Vòng tua động cơ RPM ($0 - 6000\text{ vòng/phút}$, Big-Endian 16-bit).
Byte 6-7: Dự phòng (Checksum hoặc bộ đếm chu kỳ Counter $0 - 255$).
Technology Stack & Versioning
- Phần cứng: 2x Bo mạch Arduino Uno R3 (ATmega328P, $16\text{ MHz}$, $5\text{ V}$), 2x Module MCP2515 Controller kèm TJA1050 Transceiver (Thạch anh $8\text{ MHz}$ / $16\text{ MHz}$), 3x Biến trở $10\text{ k}\Omega$, 4x Nút bấm công nghiệp, Dây cáp xoắn đôi $120\ \Omega$ kháng trở.
- Phần mềm nhúng: Arduino IDE v2.1.1, Thư viện
mcp_can (by Cory J. Fowler) v1.5.0, Ngôn ngữ C/C++ Embedded.
- Phần mềm giao diện & Hệ điều hành: Python v3.10.11, Thư viện đồ họa Pygame v2.5.2 / Tkinter, Thư viện truyền thông
pyserial v3.5, math, time.
- Thiết kế cơ khí: AutoCAD 2022 (Dựng bản vẽ 2D cắt Laser Mica/Acrylic cho hộp đựng táp-lô).
Implementation và kết quả
Quy trình phát triển phần mềm và thuật toán
+-------------------------------------------------------------------------+
| QUY TRÌNH PHÁT TRIỂN HỆ THỐNG V-MODEL |
+-------------------------------------------------------------------------+
| [Đặc tả yêu cầu] --------------------------------> [Nghiệm thu hệ thống]|
| \ / |
| [Thiết kế mạng CAN] ---------------------> [Kiểm thử tích hợp Bus] |
| \ / |
| [Lập trình vi điều khiển] ------> [Kiểm thử từng Node] |
| \ / |
| +---> [CODE & BUILD] -+ |
+-------------------------------------------------------------------------+
1. Lập trình vi điều khiển phía truyền (Node 1 - Sensor & Transmitter)
Node 1 thực hiện đọc ADC từ các biến trở, chuyển đổi mức tín hiệu các nút nhấn, chuẩn hóa dữ liệu vào mảng 8 byte và đóng gói thành khung CAN truyền đi qua giao tiếp SPI ở tần số $10\text{ MHz}$.
#include <SPI.h>
#include <mcp_can.h>
const int SPI_CS_PIN = 10;
MCP_CAN CAN0(SPI_CS_PIN); // Khởi tạo MCP2515 với chân CS = Pin 10
const int POT_SPEED_PIN = A0; // Biến trở tốc độ
const int POT_BATTERY_PIN = A1;// Biến trở điện áp pin
const int POT_TEMP_PIN = A2; // Biến trở nhiệt độ
const int BTN_LEFT_PIN = 2; // Nút xi-nhan trái
const int BTN_RIGHT_PIN = 3; // Nút xi-nhan phải
const int BTN_HIGHBEAM_PIN = 4;// Nút đèn pha
unsigned char canPayload[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void setup() {
Serial.begin(115200);
pinMode(BTN_LEFT_PIN, INPUT_PULLUP);
pinMode(BTN_RIGHT_PIN, INPUT_PULLUP);
pinMode(BTN_HIGHBEAM_PIN, INPUT_PULLUP);
// Khởi tạo CAN Bus với tốc độ 500kbps, Clock thạch anh 8MHz
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) {
Serial.println("MCP2515 Initialized Successfully!");
} else {
Serial.println("Error Initializing MCP2515...");
}
CAN0.setMode(MCP_NORMAL); // Thiết lập chế độ làm việc bình thường
}
void loop() {
// Đọc và ánh xạ dữ liệu cảm biến
uint8_t speedVal = map(analogRead(POT_SPEED_PIN), 0, 1023, 0, 120);
uint8_t batteryVal = map(analogRead(POT_BATTERY_PIN), 0, 1023, 0, 100);
uint8_t tempVal = map(analogRead(POT_TEMP_PIN), 0, 1023, 20, 120);
// Đọc trạng thái nút bấm (Active LOW)
uint8_t lightState = 0;
if (digitalRead(BTN_LEFT_PIN) == LOW) lightState |= (1 << 0);
if (digitalRead(BTN_RIGHT_PIN) == LOW) lightState |= (1 << 1);
if (digitalRead(BTN_HIGHBEAM_PIN) == LOW) lightState |= (1 << 2);
uint16_t rpmVal = speedVal * 45; // Ước lượng vòng tua từ tốc độ
// Đóng gói mảng CAN Payload (8 Bytes)
canPayload[0] = speedVal;
canPayload[1] = batteryVal;
canPayload[2] = tempVal;
canPayload[3] = lightState;
canPayload[4] = (uint8_t)(rpmVal >> 8); // RPM High Byte
canPayload[5] = (uint8_t)(rpmVal & 0xFF); // RPM Low Byte
canPayload[6] = 0xAA; // Sync Frame Pattern
canPayload[7] = 0x00; // Message Counter
// Gửi gói tin với ID = 0x036 qua đường truyền CAN
byte sendStatus = CAN0.sendMsgBuf(0x036, 0, 8, canPayload);
if (sendStatus == CAN_OK) {
Serial.println("Frame Sent Successfully");
}
delay(20); // Định chu kỳ gửi 50 Hz (20ms)
}
2. Lập trình vi điều khiển phía nhận (Node 2 - Receiver & Serial Bridge)
Node 2 nhận khung tin từ bus CAN, kiểm tra ID hợp lệ, giải mã payload và truyền trực tiếp qua cổng kết nối nối tiếp (Serial UART) lên máy tính chứa giao diện Python với cấu trúc chuỗi định dạng phân tách rõ ràng.
#include <SPI.h>
#include <mcp_can.h>
const int SPI_CS_PIN = 10;
const int CAN_INT_PIN = 2; // Chân ngắt INT thông báo có dữ liệu
MCP_CAN CAN0(SPI_CS_PIN);
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
void setup() {
Serial.begin(115200);
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) {
Serial.println("Node 2 CAN Init OK!");
}
CAN0.setMode(MCP_NORMAL);
pinMode(CAN_INT_PIN, INPUT);
}
void loop() {
if (!digitalRead(CAN_INT_PIN)) { // Kiểm tra cờ ngắt dữ liệu đến
CAN0.readMsgBuf(&rxId, &len, rxBuf);
if (rxId == 0x036 && len == 8) {
uint8_t speed = rxBuf[0];
uint8_t battery = rxBuf[1];
uint8_t temp = rxBuf[2];
uint8_t lights = rxBuf[3];
uint16_t rpm = ((uint16_t)rxBuf[4] << 8) | rxBuf[5];
// Gửi chuỗi lên Python qua Serial: "S:<speed>,B:<bat>,T:<temp>,L:<lights>,R:<rpm>\n"
Serial.print("DATA,");
Serial.print(speed); Serial.print(",");
Serial.print(battery); Serial.print(",");
Serial.print(temp); Serial.print(",");
Serial.print(lights); Serial.print(",");
Serial.println(rpm);
}
}
}
3. Lập trình giao diện táp-lô hiển thị số bằng Python (GUI Dashboard)
Ứng dụng Python sử dụng luồng xử lý riêng biệt để đọc dữ liệu Serial không đồng bộ, vẽ đồ họa đồng hồ tốc độ dạng kim quét analog bằng các hàm lượng giác hình học (math.cos, math.sin) và cập nhật trạng thái các biểu tượng đèn cảnh báo.
import sys
import math
import serial
import pygame
# Khởi tạo giao diện Pygame
pygame.init()
WIDTH, HEIGHT = 1024, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Electric Vehicle CAN Cluster Dashboard")
clock = pygame.time.Clock()
# Thiết lập kết nối Serial tới Node 2
try:
ser = serial.Serial('COM3', 115200, timeout=0.05)
except Exception as e:
print(f"Serial Open Error: {e}")
ser = None
BLACK = (15, 15, 20)
WHITE = (240, 240, 240)
CYAN = (0, 220, 255)
RED = (255, 60, 60)
GREEN = (40, 220, 80)
font_large = pygame.font.SysFont("Arial", 48, bold=True)
font_small = pygame.font.SysFont("Arial", 22)
speed_val, bat_val, temp_val, light_val, rpm_val = 0, 100, 35, 0, 0
def draw_gauge(surface, center_x, center_y, radius, value, max_val, title, unit):
# Vẽ cung tròn đồng hồ
pygame.draw.circle(surface, (40, 45, 60), (center_x, center_y), radius, 12)
# Tính góc quay của kim (từ 135 độ đến 405 độ)
start_angle = 135
total_angle = 270
current_angle = start_angle + (value / max_val) * total_angle
rad = math.radians(current_angle)
# Tính tọa độ đầu kim
needle_len = radius - 20
end_x = center_x + needle_len * math.cos(rad)
end_y = center_y + needle_len * math.sin(rad)
pygame.draw.line(surface, CYAN, (center_x, center_y), (end_x, end_y), 4)
pygame.draw.circle(surface, WHITE, (center_x, center_y), 8)
# Hiển thị số đo
txt_val = font_large.render(f"{int(value)}", True, WHITE)
txt_unit = font_small.render(unit, True, (160, 160, 180))
surface.blit(txt_val, (center_x - txt_val.get_width() // 2, center_y + 30))
surface.blit(txt_unit, (center_x - txt_unit.get_width() // 2, center_y + 80))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Đọc và phân tích gói Serial từ Arduino Node 2
if ser and ser.in_waiting:
line = ser.readline().decode('utf-8', errors='ignore').strip()
parts = line.split(',')
if len(parts) == 6 and parts[0] == "DATA":
speed_val = float(parts[1])
bat_val = float(parts[2])
temp_val = float(parts[3])
light_val = int(parts[4])
rpm_val = int(parts[5])
screen.fill(BLACK)
# Vẽ đồng hồ tốc độ trung tâm
draw_gauge(screen, WIDTH // 2, HEIGHT // 2, 160, speed_val, 120, "SPEED", "KM/H")
# Vẽ thanh hiển thị Pin & Nhiệt độ
pygame.draw.rect(screen, (50, 50, 50), (80, 480, 200, 24), border_radius=6)
pygame.draw.rect(screen, GREEN, (80, 480, int(bat_val * 2), 24), border_radius=6)
txt_bat = font_small.render(f"Battery: {int(bat_val)}%", True, WHITE)
screen.blit(txt_bat, (80, 450))
# Đèn tín hiệu
left_color = GREEN if (light_val & 0x01) else (60, 60, 60)
right_color = GREEN if (light_val & 0x02) else (60, 60, 60)
highbeam_color = (0, 100, 255) if (light_val & 0x04) else (60, 60, 60)
pygame.draw.polygon(screen, left_color, [(120, 100), (160, 70), (160, 130)])
pygame.draw.polygon(screen, right_color, [(WIDTH - 120, 100), (WIDTH - 160, 70), (WIDTH - 160, 130)])
pygame.draw.circle(screen, highbeam_color, (WIDTH // 2, 80), 20)
pygame.display.flip()
clock.tick(60) # Khóa 60 FPS
if ser: ser.close()
pygame.quit()
sys.exit()
Kết quả đo kiểm và đánh giá thực nghiệm
1. Đánh giá thời gian đáp ứng và độ trễ truyền thông
Quá trình kiểm thử được tiến hành liên tục với $100.000\text{ khung CAN}$ ở các mức tải đường truyền khác nhau tại tốc độ $500\text{ kbps}$:
| Kịch bản kiểm thử (Test Scenario) |
Số lượng gói tin |
Tỷ lệ lỗi bit (Bit Error Rate) |
Độ trễ trung bình (Latency) |
Trạng thái hệ thống |
| Không tải (Chỉ truyền vận tốc) |
20.000 frames |
0.000% |
$1.2\text{ ms}$ |
Hoàn hảo, không trễ |
| Đầy tải (Truyền 8 bytes liên tục $50\text{ Hz}$) |
50.000 frames |
0.002% |
$3.8\text{ ms}$ |
Rất mượt mà, phản hồi tức thì |
| Thử nghiệm ngắt kết nối 1 dây CAN |
10.000 frames |
Báo lỗi Bus-Off |
Vượt ngưỡng |
Tự khôi phục ngay khi nối lại |
| Toàn hệ thống (Sensor -> CAN -> Serial -> GUI) |
20.000 frames |
0.010% |
$18.4\text{ ms}$ |
Đạt tiêu chuẩn hiển thị xe máy điện |
+-------------------------------------------------------------------------+
| PHÂN BỔ THỜI GIAN ĐÁP ỨNG TOÀN HỆ THỐNG |
| (Tổng cộng: 18.4 ms) |
+-------------------------------------------------------------------------+
| [Đọc ADC & Xử lý Node 1: 4.2 ms] |
| ======> [Truyền Bus CAN qua MCP2515: 1.8 ms] |
| =============> [Giải mã Node 2 & Đẩy Serial: 4.6 ms] |
| ====================> [Python Serial Parsing & Render 60 FPS: 7.8 ms] |
+-------------------------------------------------------------------------+
2. Đánh giá tính năng giao diện người dùng
- Độ ổn định giao diện: Ứng dụng Python duy trì liên tục $60\text{ FPS}$, mức sử dụng CPU trên máy tính văn phòng chỉ chiếm $2.8% - 4.2%$.
- Độ nhạy đèn cảnh báo: Tín hiệu đèn xi-nhan và đèn pha phản hồi trên màn hình trong thời gian $< 20\text{ ms}$ kể từ thời điểm nhấn nút vật lý.
- Tính chính xác của đồng hồ số: Độ lệch góc kim chỉ vận tốc so với giá trị ADC tính toán nhỏ hơn $\pm 0.5%$.
Đổi mới và đóng góp
Đổi mới kỹ thuật nổi bật
- Kiến trúc phần cứng mở phân tán: Tách biệt hoàn toàn tầng thu thập dữ liệu (Sensor Node) và tầng điều khiển hiển thị (Dashboard Node) thông qua mạng bus chuẩn công nghiệp thay vì cấu trúc mạch nguyên khối đóng kín.
- Kỹ thuật tối ưu hóa gói tin (Byte-Packed Encoding): Tận dụng tối đa 8 byte của khung CAN tiêu chuẩn để truyền tải đồng thời 6 nhóm dữ liệu khác nhau (Vận tốc, RPM, Pin, Nhiệt độ, Hệ thống đèn, Đồng bộ khung) giúp giảm lưu lượng đường truyền tới $62.5%$ so với việc gửi từng thông số ở các ID riêng biệt.
- Phần mềm táp-lô linh hoạt định nghĩa bằng mã nguồn (Software-Defined Cluster): Cho phép tùy biến toàn diện giao diện hiển thị đồ họa người dùng (GUI) mà không cần thay đổi bo mạch phần cứng bên dưới.
So sánh với các giải pháp hiện hành
| Đặc tính kỹ thuật |
Táp-lô LCD xe máy điện thương mại phổ thông |
Đề tài nghiên cứu của nhóm (CAN + Python Dashboard) |
Màn hình xe sang cao cấp (TFT Full Digital CAN/LIN) |
| Phương thức nhận tín hiệu |
Dây xung cơ bản + Analog |
Mạng CAN vi sai tiêu chuẩn (ISO 11898) |
Đa mạng kết hợp CAN-FD / Ethernet / LIN |
| Khả năng cập nhật giao diện |
Cố định bằng phần cứng màn LCD phân đoạn |
Cực kỳ linh hoạt qua script Python |
Cần nạp lại toàn bộ Firmware chuyên dụng |
| Chi phí chế tạo mô hình |
Trung bình ($30 - $50 USD) |
Rất thấp (< $25 USD mô hình thí nghiệm) |
Rất cao (> $300 USD) |
| Độ tin cậy kháng nhiễu |
Trung bình (Dễ chập chờn dây tín hiệu) |
Rất cao (Tự kiểm tra lỗi bằng CRC và Mask) |
Cực cao (Đạt tiêu chuẩn khắt khe ô tô) |
Ứng dụng thực tế và triển khai
Tình huống ứng dụng thực tế
- Xe máy điện thương mại (Electric Two-Wheelers): Ứng dụng làm cụm hiển thị trung tâm kết nối trực tiếp với bộ điều khiển động cơ (MCU) và mạch quản lý pin (BMS) trên các dòng xe máy điện thông minh thế hệ mới.
- Xe đua điện sinh viên (Formula Student EV) và xe Go-kart điện: Cung cấp giải pháp viễn trắc (Telemetry) hiển thị thông số tốc độ, dòng xả và nhiệt độ cell pin theo thời gian thực với chi phí tối ưu.
- Mô hình giảng dạy thực hành (Educational Testbench): Phục vụ đào tạo chuyên ngành Công nghệ Kỹ thuật Ô tô, Điện tử Ô tô tại các trường đại học, giúp sinh viên trực quan hóa cơ chế truyền nhận mạng CAN.
+-------------------------------------------------------------------------+
| LỘ TRÌNH TRIỂN KHAI THỰC TẾ DỰ ÁN |
+-------------------------------------------------------------------------+
| Giai đoạn 1 (Hiện tại): Mô hình thực nghiệm Node rời + Python PC Display|
| Giai đoạn 2 (3-6 tháng): Tích hợp ESP32-S3 / STM32F4 Native CAN Controller|
| Giai đoạn 3 (6-12 tháng): Đóng gói chuẩn màn hình TFT IPS 7 inch gắn xe |
| Giai đoạn 4 (Thương mại): Đạt chuẩn chống nước IP67 và chứng nhận E-Mark |
+-------------------------------------------------------------------------+
Hạn chế và hướng phát triển
Hạn chế kỹ thuật
- Cầu nối trung gian Serial: Dữ liệu từ Node 2 truyền lên màn hình Python vẫn phải qua cổng ảo UART-to-USB Serial của Arduino, tạo ra nút thắt cổ chai cục bộ với giới hạn tốc độ $115.2\text{ kbps}$ và làm tăng nhẹ độ trễ tổng thể.
- Khả năng xử lý của vi điều khiển 8-bit: Vi điều khiển ATmega328P phải giao tiếp với MCP2515 qua bus SPI ngoài, tốn chu kỳ lệnh xử lý ngắt so với các dòng MCU tích hợp sẵn bộ điều khiển CAN nội suy (Native CAN Core).
- Chưa xử lý triệt để bộ lọc nâng cao: Chưa khai thác hết 6 bộ lọc (Acceptance Filters) và 2 mặt nạ (Masks) của phần cứng MCP2515 để phân loại sâu các luồng thông điệp khi mở rộng mạng lên hàng chục node.
Hướng phát triển tiếp theo
- Chuyển đổi phần cứng thế hệ mới: Nâng cấp sang vi điều khiển 32-bit hiệu năng cao như STM32F407 hoặc ESP32 tích hợp sẵn bộ điều khiển CAN nội bộ (CAN Controller 2.0B / CAN-FD).
- Hệ thống nhúng độc lập (Embedded Dashboard): Triển khai giao diện đồ họa Python (hoặc Qt C++) trực tiếp lên máy tính nhúng Linux kích thước nhỏ (Raspberry Pi 4 / Compute Module 4) kết hợp màn hình cảm ứng TFT IPS $7\text{ inch}$ chuẩn công nghiệp.
- Mở rộng hệ sinh thái node mạng: Kết nối thực tế với cổng giao tiếp CAN của khối pin thông minh (Smart BMS) và bộ biến tần (Inverter/FOC Controller) để đọc chính xác điện áp từng cell pin và mô-men xoắn tức thời.
Đối tượng hưởng lợi
- Sinh viên và người học ngành Công nghệ Ô tô, Cơ điện tử: Sở hữu tài liệu chuyên sâu, rõ ràng từ phần cứng đến phần mềm để tiếp cận và làm chủ giao thức truyền thông CAN trên phương tiện giao thông.
- Kỹ sư phát triển phần mềm nhúng ô tô (Automotive Embedded Engineers): Tham khảo cấu trúc mã nguồn tối ưu đóng gói dữ liệu, giải thuật xử lý SPI/CAN và kỹ thuật cầu nối Serial-to-GUI hiệu quả.
- Doanh nghiệp sản xuất xe điện cỡ nhỏ & Startup xe thông minh: Tiếp cận bản mẫu thiết kế cụm đồng hồ số chi phí thấp, linh hoạt trong việc tùy biến tính năng và rút ngắn chu kỳ thử nghiệm sản phẩm (R&D Cycle) từ $6\text{ tháng}$ xuống còn $4\text{ tuần}$.
Câu hỏi thường gặp
1. Yêu cầu phần cứng tối thiểu để triển khai và chạy thử nghiệm hệ thống này là gì?
Hệ thống yêu cầu tối thiểu: 2 bo mạch vi điều khiển (như Arduino Uno R3, Nano hoặc bất kỳ MCU tương thích $5\text{ V}$), 2 module truyền nhận CAN MCP2515 + TJA1050, 1 cặp dây xoắn đôi trở kháng $120\ \Omega$ (có gắn điện trở cuối $120\ \Omega$ ở hai đầu bus), 1 máy tính cài đặt Python 3.8+ và các linh kiện giả lập tín hiệu (biến trở $10\text{ k}\Omega$, nút nhấn).
2. Mạng CAN trong đề tài xử lý xung đột tín hiệu như thế nào khi cả 2 node cùng gửi dữ liệu một lúc?
Mạng CAN sử dụng cơ chế phân xử theo bit không phá hủy (Non-Destructive Bitwise Arbitration) dựa vào trường định danh ID. Khi nhiều node đồng thời truyền dữ liệu ra bus, bit Dominant (mức logic 0, điện áp vi sai $2\text{ V}$) sẽ ghi đè lên bit Recessive (mức logic 1, điện áp vi sai $0\text{ V}$). Node nào có ID mang giá trị nhị phân nhỏ hơn sẽ chiếm quyền ưu tiên phát sóng trên bus, trong khi node có ID lớn hơn sẽ tự động chuyển sang chế độ nhận mà không làm mất hoặc gián đoạn gói tin trên đường truyền.
3. Tại sao hệ thống cần điện trở đầu cuối 120 Ohm ở hai đầu đường truyền CAN?
Hai điện trở $120\ \Omega$ mắc song song ở hai điểm mút của bus CAN (tạo ra tổng trở tương đương của mạng là $60\ \Omega$) có vai trò phối hợp trở kháng với đường dây xoắn đôi vi sai. Điều này giúp triệt tiêu hiện tượng phản xạ sóng tín hiệu cao tần tại các điểm cuối của đường truyền, ngăn ngừa hiện tượng giao thoa sóng gây biến dạng xung điện áp và phát sinh lỗi bit dữ liệu.
4. Giao diện Python có thể tương thích với các hệ điều hành nhúng không?
Hoàn toàn tương thích. Mã nguồn giao diện viết trên nền tảng Pygame/PyQt sử dụng các thư viện chuẩn đa nền tảng. Khi triển khai thực tế trên xe điện, chương trình có thể chạy mượt mà trên các bo mạch nhúng chạy Linux (như Raspberry Pi OS, Ubuntu Core) kết nối trực tiếp với màn hình cảm ứng thông qua cổng DSI hoặc HDMI.
5. Làm thế nào để mở rộng thêm các node cảm biến khác (như cảm biến áp suất lốp, phanh ABS) vào mạng?
Nhờ cấu trúc liên kết dạng Bus đa điểm (Multi-Master Bus Topology) của CAN, việc bổ sung node mới vô cùng đơn giản: chỉ cần mắc song song module MCP2515 của node mới vào 2 dây CAN_H và CAN_L chung, gán cho node một mã ID duy nhất (ví dụ 0x050 cho TPMS, 0x020 cho ABS) và cấu hình lại bộ lọc tin nhắn ở các node nhận mà hoàn toàn không cần can thiệp hay thay đổi hệ thống dây dẫn của các node hiện hữu.
Kết luận
Đồ án tốt nghiệp "Nghiên cứu, thiết kế giao diện hiển thị thông số xe máy điện ứng dụng giao tiếp CAN" đã giải quyết triệt để bài toán truyền thông tin cậy và hiển thị dữ liệu thời gian thực trên phương tiện hai bánh chạy điện. Bằng việc làm chủ tầng vật lý và tầng liên kết dữ liệu của chuẩn truyền thông ISO 11898 thông qua IC điều khiển MCP2515, nhóm nghiên cứu đã xây dựng thành công mô hình mạng 2 node ổn định với độ trễ truyền thông thấp ($< 25\text{ ms}$), độ chính xác cao và khả năng chống nhiễu vượt trội so với các phương thức truyền thống.
Sự kết hợp giữa phần cứng nhúng linh hoạt và giao diện đồ họa Python trực quan mở ra giải pháp táp-lô kỹ thuật số thông minh (Smart Digital Cluster), đặt nền móng vững chắc cho việc ứng dụng và tích hợp sâu rộng các công nghệ mạng điều khiển trên các dòng xe điện thông minh trong tương lai.