CAN Protocol Reference
The AddVantage PPG uses J1939 protocol over CAN bus at 250 kbit/s to receive engine data from the ECU.
Overview
J1939 is a higher-layer protocol built on CAN 2.0B (29-bit identifiers). The 29-bit arbitration ID contains:
Bits |
Field |
Description |
|---|---|---|
28-26 |
Priority |
0-7 (lower = higher priority) |
25-24 |
Reserved |
Usually 0 |
23-16 |
PGN (high) |
Parameter Group Number |
15-8 |
PGN (low) |
|
7-0 |
Source Address |
Transmitting ECU address |
Extracting PGN from CAN ID
uint32_t extract_pgn(uint32_t can_id) {
// Mask off priority and source address
uint32_t pgn = (can_id >> 8) & 0x3FFFF;
// For PDU1 format (PS < 240), PS is destination address
if (((pgn >> 8) & 0xFF) < 240) {
pgn &= 0x3FF00; // Mask off PS field
}
return pgn;
}
Supported PGNs
EEC1 (61444) - Electronic Engine Controller 1
Primary engine parameters. Transmitted at 10-100ms intervals.
Byte |
Parameter |
Resolution |
Range |
|---|---|---|---|
0 |
Engine Torque Mode |
4 bits |
0-15 |
1 |
Driver Demand Torque |
1%/bit - 125 |
-125 to 125% |
2 |
Actual Engine Torque |
1%/bit - 125 |
-125 to 125% |
3-4 |
Engine Speed |
0.125 RPM/bit |
0-8031.875 RPM |
5 |
Source Address |
- |
0-255 |
6-7 |
Starter Mode |
- |
- |
Parsing Engine Speed (RPM):
uint16_t speed_raw = data[3] | (data[4] << 8);
uint16_t rpm = (uint16_t)(speed_raw * 0.125);
Parsing Torque (%):
int8_t torque = data[2] - 125; // Range: -125% to +125%
ET1 (65262) - Engine Temperature 1
Engine temperature sensors. Transmitted at 1000ms intervals.
Byte |
Parameter |
Resolution |
Range |
|---|---|---|---|
0 |
Engine Coolant Temp |
1°C/bit - 40 |
-40 to 210°C |
1 |
Fuel Temp |
1°C/bit - 40 |
-40 to 210°C |
2-3 |
Engine Oil Temp |
0.03125°C/bit - 273 |
-273 to 1735°C |
4-5 |
Turbo Oil Temp |
0.03125°C/bit - 273 |
-273 to 1735°C |
6 |
Engine Intercooler Temp |
1°C/bit - 40 |
-40 to 210°C |
7 |
Engine Intercooler Thermostat |
0.4%/bit |
0-100% |
Parsing Coolant Temperature:
int16_t coolant_temp = data[0] - 40; // Range: -40°C to +210°C
LFE (65266) - Fuel Economy
Fuel consumption data. Transmitted at 100ms intervals.
Byte |
Parameter |
Resolution |
Range |
|---|---|---|---|
0-1 |
Fuel Rate |
0.05 L/h per bit |
0-3212.75 L/h |
2-3 |
Instantaneous Fuel Economy |
1/512 km/L per bit |
0-125.5 km/L |
4-5 |
Average Fuel Economy |
1/512 km/L per bit |
0-125.5 km/L |
6 |
Throttle Position |
0.4%/bit |
0-100% |
7 |
Reserved |
- |
- |
Parsing Fuel Rate:
uint16_t fuel_raw = data[0] | (data[1] << 8);
float fuel_rate_lph = fuel_raw * 0.05; // Liters per hour
ETC2 (61445) - Electronic Transmission Controller 2
Transmission data (optional).
Byte |
Parameter |
Resolution |
Range |
|---|---|---|---|
0 |
Selected Gear |
- |
-125 to 125 |
1-2 |
Current Gear Ratio |
0.001/bit |
0-64.255 |
3 |
Current Gear |
- |
-125 to 125 |
4-5 |
Transmission Range |
2 bits per state |
- |
Error Values
J1939 uses special values to indicate errors or unavailable data:
Value |
Meaning |
|---|---|
0xFE |
Parameter error |
0xFF |
Not available |
0xFFFE (16-bit) |
Parameter error |
0xFFFF (16-bit) |
Not available |
Always check for these values before using data:
if (data[0] != 0xFF) {
coolant_temp = data[0] - 40;
} else {
// Data not available
}
CAN Hardware Configuration
The SKEAZ128 MSCAN peripheral is configured for:
Bit Rate: 250 kbit/s
Sample Point: ~75%
Bus Timing: Prescaler depends on bus clock
Filter Configuration
The firmware accepts all J1939 messages (no filtering). In a production system, you may want to filter for specific PGNs:
// Example: Accept only EEC1, ET1, LFE
CAN1_SetAcceptanceFilter(PGN_EEC1 << 8, 0x00FFFF00);
CAN1_SetAcceptanceFilter(PGN_ET1 << 8, 0x00FFFF00);
CAN1_SetAcceptanceFilter(PGN_LFE << 8, 0x00FFFF00);
Wiring
Standard CAN bus wiring:
Pin |
Function |
Color (typical) |
|---|---|---|
CAN_H |
CAN High |
Yellow |
CAN_L |
CAN Low |
Green |
GND |
Ground |
Black |
Termination: 120Ω resistor between CAN_H and CAN_L at each end of the bus.
Debugging with PCAN
Use the CAN viewer tool to monitor live data:
python tools/can_viewer.py
Or validate CAN data against ECU telemetry:
python tools/can_validate.py --duration 10 --tolerance 5
Message Timing
Expected message rates from a typical diesel ECU:
PGN |
Rate |
Use Case |
|---|---|---|
EEC1 |
10-20ms |
Engine speed control |
ET1 |
1000ms |
Temperature monitoring |
LFE |
100ms |
Fuel calculation |
The PPG samples CAN data continuously and uses the most recent values for fuel calculations.