Objective
A friend runs electric Ford Ranger conversions on NiMH packs, and one of his trucks developed a battery-side fault. The battery management system narrates everything it knows onto the CAN bus — but his logger captured that traffic as plain text, one frame per line, which no proper CAN analysis tool will open. The job was to build a conversion tool that turns those raw text logs into the .trc trace format native to PEAK-System's PCAN tools, so the BMS traffic could be filtered, decoded, and replayed in PCAN-View instead of being eyeballed in a text editor.
The Raw Data
The logs arrived as text files with one CAN frame per line: a timestamp in seconds, the (extended) CAN ID in hex, the DLC, and the payload bytes:
0.001 1F334455 8 01 02 03 04 05 06 07 08
Everything needed to reconstruct the bus traffic is there — but trace-analysis tools expect a structured trace file. The .trc format adds what the raw lines lack: a header describing the capture, a record number per frame, the channel, the direction (Tx/Rx), and a frame-type flag, all in fixed columns the software can parse.
The Conversion
The converter is a small Python script: split each line into its fields, then re-emit it as a numbered .trc record under a generated header. The core of it:
# Sample raw CAN data (timestamp, CAN ID, DLC, data)
raw_data = [
"0.001 1F334455 8 01 02 03 04 05 06 07 08",
# ... the rest of the log
]
# Convert to .trc format
with open("output.trc", "w") as trc_file:
# Write a header (customize as needed)
trc_file.write("date 2023-04-01 base hex timestamps absolute\n")
trc_file.write("no internal events logged\n")
# Begin with line 2 after the header
line_no = 2
for line in raw_data:
parts = line.split()
timestamp = parts[0]
can_id = parts[1]
dlc = parts[2]
data = ' '.join(parts[3:])
# Format line according to .trc specifications
trc_line = f"{line_no} {timestamp} 1 Rx d {dlc} {can_id} {data}\n"
trc_file.write(trc_line)
line_no += 1
The structure is simple on purpose: the parsing assumptions live in one place, so when a log from a different tap shows up with a different line shape, only the split() mapping changes — the .trc emission stays put. Every captured frame is marked Rx, since the logger was a passive listener on the bus.
The Diagnosis
With the logs converted, the BMS traffic could finally be loaded into PCAN-View, filtered by CAN ID, and walked frame-by-frame on a real timeline. The trace pointed to a contactor fault: the high-voltage contactor — the relay that connects the pack to the rest of the truck — wasn't behaving the way the BMS expected, and the converted traces made the mismatch between what the BMS commanded and what it saw visible enough to pin down. A text file full of hex became a diagnosis.