CAN bus arbitration

Several ECUs share one wire. They all start talking at the same instant — and yet none of their messages are destroyed. Watch how a bit of electrical trickery turns a collision into a priority auction, decided one bit at a time, and how the losers eventually get their turn too.

The trick in one paragraph

The CAN bus is wired-AND. Any node can pull the line down to 0 (a dominant bit), but the line only floats up to 1 (a recessive bit) when every node is sending 1. Each node transmits its message ID one bit at a time, MSB first, and listens to the line as it goes. The instant a node sends a recessive 1 but reads back a dominant 0, it knows somebody else is sending a higher-priority message, so it shuts up and becomes a receiver. The lowest ID wins this round and transmits its DATA. The frame ends with EOF — 7 recessive bits — followed by IFS, 3 more recessive bits of interframe space. Once any node has seen the bus stay recessive that long, it knows the bus is idle and may start a new transmission. That’s the cue for the losers to re-arbitrate, and the priority cascade rolls on until everybody has spoken.

Nodes

ID width

Run the auction

600ms per bit
press Step or Play

Bit-by-bit on the wire

0 — dominant (line pulled down) 1 — recessive (line floats up) backed off — waiting for next round this bit cost the node arbitration DATA — winner’s payload + CRC EOF — 7 recessive bits, frame ends IFS — 3 recessive bits, bus idle, next round may begin

Result

Things to try

  1. Press Play with the defaults. Round 1: at b5, Radio sends 1 while the others send 0 — Radio backs off. At b4, Engine sends 1 while Brake sends 0 — Engine backs off. Brake transmits its frame uncontested. Round 2: Engine and Radio re-enter; Engine wins. Round 3: Radio is alone and finally gets the bus. Lower ID = higher priority, every time.
  2. Edit the IDs so two nodes start with the same high-order bits but diverge later (e.g. 0x10 vs 0x11). Watch the loser hold on all the way until the very last bit before being knocked out.
  3. Give two nodes the same ID. The round ends in a tie — in real CAN, message IDs must be unique, exactly because the protocol has no other tie-breaker. (After arbitration, both nodes would corrupt each other’s data and trigger an error frame; the cascade halts.)
  4. Set IDs to 0x00, 0x3F, and 0x20. The all-zeros node wins round 1 on the very first ID bit. In round 2, 0x20 beats 0x3F just as easily.
  5. Switch to 11-bit (real CAN) mode — the same logic plays out across more bits, so two close IDs (say 0x100 and 0x101) only diverge at the very last bit. The loser stays in the running for the entire arbitration field before backing off.
  6. Imagine the bus the other way around: if recessive were 0 and dominant were 1 (wired-OR), then the highest ID would win. The bus is wired-AND specifically so that lower numerical IDs map to higher priority — a convention that lets you sort messages by priority just by sorting their IDs.
What this simulator skips

Real CAN frames are more than the arbitration field. Each frame begins with a single dominant Start-of-Frame bit (omitted here — it doesn’t affect who wins), then the 11-bit (or 29-bit, in extended CAN) identifier, then the RTR bit, control field, data field, CRC, ACK slot, and EOF. The whole tail end is what we collapse into one FRAME tile. Bit timing is also more nuanced in real hardware: each bit is divided into segments and there’s a sample point near the end where the receiver reads the bus and re-synchronises. None of that affects who wins arbitration, which is why we leave it out.

Also: a node only enters arbitration when it has something to send and the bus has been idle long enough. Here we just assume every node is ready and queues up the moment the previous frame finishes.