Skip to content

CAN

This page teaches how Classical CAN exposes priority, cadence, and frame shape before it exposes signal meaning.

Status Examples Runtime example Source posture
final-copy synthetic/passive available standards metadata plus public/tooling cross-checks

A Concrete Artifact

# synthetic passive capture fragment
t=0.000000  0x080  01
t=0.000006  0x123  10 27 20 27 18 27 22 27
t=0.020005  0x123  20 27 21 27 19 27 22 27
t=0.040006  0x123  1f 27 20 27 18 27 23 27
t=0.050000  0x321  5a 00

Synthetic

Synthetic offline sample for explanation; not a real operational trace or live-system instruction.

Inspection Trap

A CAN frame can look complete while its payload is still semantically opaque. The identifier participates in arbitration and names a message shape; it is not automatically a sender address, an engineering value, or proof that an application used the data.

The safer claim is layered: a passive observer can first describe identifiers, payload length, payload bytes, timing, ACK/error evidence, and arbitration pressure. Signal names and units require a DBC, J1939 vocabulary, CANopen object dictionary, or OEM convention layered over the shared differential bus evidence.

Worked Decode

  1. 0x080, 0x123, and 0x321 fit the standard 11-bit identifier space in this teaching example.
  2. The identifier is treated as message identity plus arbitration priority. It is not automatically a sender address.
  3. If 0x080 and 0x123 begin together, the lower numeric identifier wins because dominant 0 bits override recessive 1 bits during arbitration.
  4. The repeated 0x123 observations add timing evidence: this identifier appears roughly every 20 ms in the synthetic trace.
  5. 0x123 carries eight payload bytes, so the Classical CAN DLC is 8 in this simplified frame.
  6. Under the page-local toy dictionary, 10 27 20 27 18 27 22 27 contains four little-endian unsigned values scaled by 0.01 km/h: 100.00, 100.16, 100.08, and 100.18 km/h.
  7. Under a different DBC, J1939 vocabulary, CANopen object dictionary, or OEM agreement, the same bytes could decode differently or not at all. A wrong DBC could still produce a plausible but false wheel speed, temperature, or actuator state.

What The Evidence Supports

The artifact supports a frame-level observer claim: the synthetic trace contains standard identifiers 0x080, 0x123, and 0x321; identifier 0x123 appears near 20 ms intervals; its first payload can be split into four toy little-endian values; and lower numeric identifiers would win arbitration in the simplified dominant/recessive model.

The trace also supports cadence hypotheses: 0x080 at 10 ms and 0x123 at 20 ms are plausible scheduler rhythms when the pattern repeats in a longer passive capture. Those are freshness and priority clues, not signal truth.

What The Evidence Does Not Support

The artifact does not prove sender identity, receiver intent, physical state, freshness beyond the observed timestamps, or application consumption. A valid CRC does not prove the payload value is fresh, physically plausible, or used by an application.

The toy wheel-speed-like values are synthetic. Without a trusted DBC, J1939 PGN/SPN definition, CANopen object dictionary, or OEM source, the payload bytes remain bytes with cadence and frame integrity evidence.

Field Layout / Anatomy

Element Shape Inspection meaning
Identifier 11 or 29 bits Arbitration priority and message identity; lower numeric values win in this simplified discussion.
DLC 0 to 8 bytes for Classical CAN Payload length evidence, not signal meaning.
Payload 0 to 8 bytes Application bytes whose semantics come from a higher-layer authority.
Dominant/recessive state bit-level bus state Enables nondestructive arbitration and bit monitoring.
CRC and ACK frame-level checks Evidence of frame integrity and reception, not proof of application-level use.
Differential pair CAN_H / CAN_L Physical evidence for the bus medium, outside the page's compliance scope.
Error confinement node behavior Faulty nodes can move toward error-passive or bus-off behavior.

Visual Model

flowchart LR engine["Engine ECU"] --- bus[("CAN_H / CAN_L shared bus")] brake["Brake controller"] --- bus cluster["Instrument cluster"] --- bus observer["Passive observer"] -. listens .-> bus bus --> evidence["IDs, payloads, cadence, errors"]
packet +1: "S" +11: "ID 0x123" +3: "Control" +4: "DLC 8" +64: "Data 10 27 20 27 18 27 22 27" +15: "CRC" +1: "C" +2: "ACK" +7: "EOF"
0x080: 00010000000
0x123: 00100100011
      ^ first differing arbitration bit; dominant 0 continues
flowchart LR a["t=0.000006<br/>0x123"] --> b["t=0.020005<br/>0x123"] b --> c["t=0.040006<br/>0x123"] c -. "expected near 20 ms" .-> d["next observation?"] d --> hypothesis["cadence evidence,<br/>not signal truth"]

Timing And Authority

Bus authority is resolved during arbitration, one bit at a time. Arbitration pressure can delay low-priority frames and distort naive period estimates. A recurring 0x080 at 10 ms and 0x123 at 20 ms may reveal scheduler rhythm even if the payload is opaque.

Semantic authority

Payload bytes need semantic authority before they become engineering values. DBC files, J1939 PGN/SPN definitions, CANopen object dictionaries, or OEM conventions turn payload bits into signal names, units, and state labels.

Failure And Ambiguity

  • A missing identifier may mean sleep, failure, capture loss, bus-off, or simply a system state where the message is not scheduled.
  • A valid CRC does not prove the payload value is fresh, physically plausible, or consumed by an application.
  • A stale or wrong DBC can produce plausible false values.
  • Arbitration pressure can delay low-priority frames and distort naive period estimates.
  • Remote frames, error frames, bit stuffing, and physical-layer details are intentionally outside the page artifact.

Python Model

The current package exposes a concrete CAN example:

"""Runnable CAN inspection example for the schoolbus binder."""

from schoolbus.protocols.can import CanFrame

frame = CanFrame(identifier=0x123, data=bytes.fromhex("10 27 20 27 18 27 22 27"))

print(frame.show_fields())
print(frame.explain())

The binder keeps that model intentionally small: identifier, payload, field display, and explanation before any semantic dictionary. For a remote frame, requested_dlc records the expected length of the corresponding data frame; the remote artifact itself has no payload and does not establish that a response occurred.

The first workbook sample pack includes a passive synthetic CAN fixture under samples/first-workbook/ that mirrors this style of identifier, DLC, and payload inspection without assigning unsupported signal truth.

Simplification

The brake/status, wheel-speed, and temperature/status meanings are synthetic. The packet diagram is a field-boundary view. It omits bit stuffing, exact inter-frame spacing, electrical design, termination, cable-length limits, and conformance timing.

Source Notes

Teaching claim Source role Limit
CAN identifiers participate in arbitration. canonical metadata Not a conformance timing table.
Payload bytes need semantic authority. de facto/proprietary format context The page-local toy dictionary is synthetic.
CRC and ACK bound frame-level evidence. public explainer Not proof of freshness or application consumption.
A remote frame may record a requested DLC. canonical metadata The model does not infer a response from the request.
This trace shows cadence reasoning. synthetic teaching artifact Not operational capture evidence.
Field Value
Governance tier Tier 1 Core Lab
Canonical source status yes
Public explainer status yes
Open-source tool status yes
Sample-data status none listed; use synthetic teaching artifacts
Confidence high
Citation specificity document-metadata-level

References

Public Sources

Project posture is aggregated in the protocol support policy, source policy, and project charter.