matlab/matlab-vehicle-network-communication
Use when setting up vehicle network communication in MATLAB using Vehicle Network Toolbox. Covers CAN/CAN FD (fully implemented), with architecture for J1939, XCP, and future protocols. Handles hardware discovery, channel creation, bus configuration, message exchange, signal encoding/decoding, and analysis across all supported vendors. (Vector, Kvaser, PEAK-System, NI, SocketCAN, MathWorks Virtual).
npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-vehicle-network-communication
ver('vnt') to verify)Guide Claude through helping users establish vehicle network communication using MATLAB Vehicle Network Toolbox. This skill covers the full workflow from hardware discovery to message exchange across all supported protocols and vendors.
Implemented protocols:
Planned protocols (architecture ready, not yet documented):
Use this decision tree to identify which protocol the user needs:
| User's Goal | Protocol | Reference Section |
|-------------|----------|-------------------|
| Send/receive CAN or CAN FD messages | CAN/CAN FD | references/can/ |
| Work with SAE J1939 parameter groups | J1939 | *Not yet documented* |
| ECU measurement or calibration via XCP/CCP | XCP | *Not yet documented* |
| General hardware discovery (any protocol) | Shared | references/shared/ |
If the user asks about a protocol not yet documented, inform them which protocols are currently covered and offer to help with those.
t = canChannelList; % CAN/CAN FD/J1939 devices
All VNT protocols share the same hardware discovery mechanism. See references/shared/hardware-discovery.md.
All protocols follow the same lifecycle pattern:
Create Channel → Configure → Start → Operate → Stop/Cleanup
Key rules:
startclear ch releases the channel (equivalent to stop + destroy)onCleanup(@() stop(ch)) for error-safe cleanupSee references/shared/channel-lifecycle.md.
| Vendor | Windows | Linux | Notes |
|--------|:-------:|:-----:|-------|
| Vector | Yes | No | Virtual channels if driver installed |
| NI | Yes | No | No channel index in constructor |
| Kvaser | Yes | Yes | Restart MATLAB after connecting hardware |
| PEAK-System | Yes | Yes | 10-arg clock-based configBusSpeed |
| SocketCAN | No | Yes | Configure speed at OS level via ip link |
| MathWorks Virtual | Yes | Yes | Always available, no driver needed |
If the user reports a CAN/CAN FD problem — "not working", "trouble", "error", "can't connect", "no messages", hardware not detected, or any communication failure — you MUST do one of the following:
digraph can_workflow {
rankdir=TB;
node [shape=box];
discover [label="1. Discover Hardware\ncanChannelList"];
decide [label="CAN Classic or CAN FD?" shape=diamond];
create_classic [label="2a. Create Channel\ncanChannel(vendor, device, ch)"];
create_fd [label="2b. Create FD Channel\ncanChannel(..., ProtocolMode='CAN FD')\nor canFDChannel(...)"];
config [label="3. Configure Bus Speed\nconfigBusSpeed (vendor-specific syntax)"];
start [label="4. Start Channel\nstart(ch)"];
operate [label="5. Transmit / Receive\ntransmit, receive\ntransmitPeriodic, transmitEvent, replay"];
cleanup [label="6. Cleanup\nstop(ch) or clear ch"];
discover -> decide;
decide -> create_classic [label="Classic"];
decide -> create_fd [label="CAN FD"];
create_classic -> config;
create_fd -> config;
config -> start;
start -> operate;
operate -> cleanup;
}
After ANY transmit, verify the bus accepted the frame before reporting success:
pause(0.5);
fprintf('TEC=%d REC=%d BusStatus=%s\n', ch.TransmitErrorCount, ch.ReceiveErrorCount, ch.BusStatus);
| Result | Action |
|--------|--------|
| TEC=0, REC=0, ErrorActive | Healthy — report success |
| TEC>0 OR REC>0 OR not ErrorActive | Unhealthy — report counters to user, route to diagnostic workflow Step 0.5. Follow diagnostic Interaction Rules (one question at a time). |
Never claim "sent successfully" from transmit returning without error. It is non-blocking and returns immediately regardless of bus state. When routing to diagnostics, do NOT list multiple possible causes — let Step 0.5 identify the root cause and ask one targeted question.
| Aspect | CAN Classic | CAN FD |
|--------|-------------|--------|
| Max payload | 8 bytes | 64 bytes |
| Message constructor | canMessage(id, ext, dlc) | canFDMessage(id, ext, dlc) or canMessage(..., ProtocolMode="CAN FD") |
| Channel creation | canChannel(vendor, device, ch) | Add 'ProtocolMode', 'CAN FD' or use canFDChannel |
| Bus speed config | Single speed | Arbitration + Data phase (vendor-specific syntax) |
| receive output | Objects or timetable | Always timetable |
| Valid DLCs | 0–8 | 0, 8, 12, 16, 20, 24, 32, 48, 64 |
These patterns are where the API behaves differently than expected. Follow these exactly.
% WRONG — will error
attachDatabase(ch, db);
ch.Database = db; % only valid for name-based filterAllowOnly
% CORRECT — attach to received message object
rxMsg = receive(ch, 1);
attachDatabase(rxMsg, db);
speed = rxMsg.Signals.EngineSpeed;
% WRONG — manual loop blocks MATLAB, timing is inaccurate
while running
pack(msg, newValue, 0, 16, 'LittleEndian');
transmit(ch, msg);
pause(0.1);
end
% CORRECT — hardware-timed, non-blocking
transmitPeriodic(ch, msg, 'On', 0.1);
start(ch);
pack(msg, newValue, 0, 16, 'LittleEndian'); % next cycle sends updated data
% WRONG — errors with "Expected NAME to be one of these types: char, cell"
filterAllowOnly(ch, [0x180 0x181]);
% CORRECT — must specify 'Standard' or 'Extended'
filterAllowOnly(ch, [0x180 0x181], 'Standard');
filterAllowOnly(ch, [0x18FEF100], 'Extended');
% MathWorks Virtual / NI — simple 3-arg form works
configBusSpeed(ch, 500000, 2000000);
% Vector / Kvaser — REQUIRES 9-arg advanced timing form
configBusSpeed(ch, 500000, 2, 6, 3, 2000000, 2, 6, 3);
% PEAK-System — REQUIRES 10-arg clock-based form
configBusSpeed(ch, 20, 5, 1, 2, 1, 2, 1, 3, 1);
% CAN FD channels ignore OutputFormat — always timetable
msgs = receive(fdCh, Inf); % returns timetable
msgs.ID % numeric vector of IDs
msgs.Data{1} % uint8 vector for first message
% WRONG: msgs(1).Data, msgs.Data(1) — these error on timetable
transmitEvent(ch, msg, 'On');
start(ch);
pack(msg, value, 0, 16, 'LittleEndian'); % this auto-transmits!
% No explicit transmit() call needed — pack triggers it
| Pitfall | Symptom | Fix |
|---------|---------|-----|
| Stale channel object | "lacks initialization access" | clear the variable or stop prior channel |
| canMessage for FD payload | "DATALENGTH must be <= 8" | Use canFDMessage or add ProtocolMode="CAN FD" |
| No acknowledging node | Transmit retries continuously | Ensure another node/channel is started on the bus |
| Claiming success without checking counters | User believes data sent; bus is ErrorPassive | ALWAYS check TEC/REC/BusStatus after transmit |
| Bus speed mismatch | Transmit succeeds, receive empty | All nodes must share same speed |
| configBusSpeed after start | Error | Must configure while channel is offline |
| Reusing variable | Error on creation | clear variable before creating new channel |
| configBusSpeed on SocketCAN | Not supported | Configure speed at OS level via ip link |
| CAN FD on PEAK-System Linux | Self-receive not supported | Use SocketCAN as workaround |
| unpack on timetable | "Incorrect number or types of inputs" | CAN FD always returns timetable; use typecast(data(1:2), 'int16') on raw bytes |
Detailed API documentation (load on demand):
canChannel, canFDChannel, vendor-specific syntaxconfigBusSpeed, vendor-specific argument countscanMessage, canFDMessage, valid FD DLCstransmit, transmitPeriodic, transmitEvent, replayreceive, SilentMode, timetable output, FIFO behaviorfilterAllowOnly, filterBlockAll, filterAllowAllcanDatabase, attachDatabase, signal-level decode/encodepack, unpack, signal extraction, byte-orderextractAll, extractRecent, extractTime, discardSee Troubleshooting Gate at the top of this section. Also route to diagnostics when the agent observes unhealthy bus state (TEC/REC > 0, BusStatus not ErrorActive) during any operation — including after transmit verification.
canChannelList, platform constraintsstart, stop, onCleanup, channel release----
Copyright 2026 The MathWorks, Inc.
----
Take matlab/matlab-vehicle-network-communication from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.