Computing stuff tied to the physical world

Yes, we CAN bus

In Hardware on May 31, 2013 at 00:01

The CAN Bus is a very interesting wired bus design, coming from the automobile industry (and probably built into every European car made today). It’s a bus with an ingenious design, avoiding bus collisions and supporting a good level of real-time responsiveness.

I’ve been intrigued by this for quite some time, and decided to dive in a bit.

There are several interesting design choices in CAN bus:

  • it’s all low-voltage, just 0..5V (even 0..3.3V) is all it takes on each connected node
  • the bus is linear, reaching from 40 m @ 1 Mbit/s to 500 m @ 125 kbit/s, or even longer
  • signalling is based on voltage between two wires, and terminated by 120 Ω on each end
  • signals are self-clocked, with bit-stuffing to insert bit-transitions when needed

But the three most surprising aspects of the CAN bus design are probably the following:

  • the design is such that collisions cannot happen: one of the two senders always wins
  • each CAN bus packet can have at most 8 bytes of data (and is CRC-checked)
  • as described recently, messages have no destination, but only a message ID (type)

What’s also interesting is that – like I2C – this protocol tends to be fully implemented in hardware, and is included in all sorts of (usually ARM-based) microcontrollers. So unlike UARTs, RS485, I2C, and SPI, you simply get complete and valid packets in and out of the peripheral. No need to deal with framing, CRC checking, or timing decisions.

You can almost feel the car-like real-time nature of these design trade-offs:

  • short packets – always! – so the bus is released very quickly, and very often
  • no collisions, i.e. no degradation in bus use and wasted retransmits as it gets busier
  • built-in prioritisation, so specific streams can be sent across with controlled latencies
  • with a 16-bit CRC on each 0..8 byte packet, chances of an undetected error are slim

Since my scope includes hardware CAN bus decoding, I decided to try it out:

SCR37

The message has an ID of 0x101 (message ID’s are either 11 or 29 bits), eight bytes of data (0xAA55AA55FF00FF00), and a CRC checksum 0x1E32. I’m using a 500 KHz bit clock.

If you look closely, you can see that there are never more than 5 identical bits in a row. That’s what bit-stuffing does: insert an opposite bit to avoid longer stretches of identical bits, as this greatly helps deduce exact timings from an incoming bit-stream.

It seems crazy to limit packets to just 8 bytes – what could possibly be done with that, without wasting it all on counters and offsets to send perhaps 4 bytes of real data in each packet? As it turns out, it really isn’t so limiting – it just takes a somewhat different mindset. And the big gain is that multiple information streams end up getting interleaved very naturally. As long as each of them is reasonable, that is: don’t expect to get more than 2 or 3 data streams across a 1 Mb/s bus, each perhaps no more than 100 kb/s. Then again, you can expect these to arrive within a very consistent and predictable time, regardless of what other lower-priority burst traffic is going on.

Neat stuff…

  1. The limitation on payloads of 4 or 8 bytes can easily be made transparent to the programmer by making an abstraction in the driver layers of course. For the sender/message IDs just the native CAN mechanism can be used, but part of the payload will then contain a couple of bits that serves as a sequence counter of multiple packages. Also an end-of-stream needs to be defined.

    The very affordable olimex STM32 (20 euros) that I am playing with currently has a CAN-bus header.

  2. As mentioned by SevenW a very useful function is the ability to multiplex the data in the message to increase the volume of data transfered. Have you looked into the Vector tools, canalyser and CANoe.

    • Those are all payware tools, as far as I can tell?

      I’m also looking into CANopen, which allows (controlled) use of extended (29-bit) ID’s, so the same tricks can be used in that context – you basically gain 18 bits of payload data by masking out the lower 18 bits when setting up receiver address filtering.

  3. We have been using CAN in several projects to replace RS485 and I really like it. On top of CAN, we use some J1939 conventions, which gives us:

    • a standard way to implement large packets
    • a standard way to do addressing (broadcast, point to point, etc)

    Some information on J1939:

    http://www.simmasoftware.com/j1939-presentation.pdf

    http://www.copperhilltech.com/a-comprehensible-guide-to-j1939-ebook-pdf/ (very good reference for CAN and J1939)

    Although J1939 was originally designed for automotive systems, it is well thought out, and the conventions are useful in many other distributed systems.

  4. Yep! all payware I’m afraid, I’m in the automotive sector so I’m happy to say it’s not me that’s paying.

  5. AFAIR, the CAN protocol itself actually does not cover PHY (layer 1) of OSI model. That means CAN does not impose any physical implementation.

    So “it’s all low-voltage” is actually right and wrong because you could aslo use CAN protocol with (on/off) light … or even sound (that could be fun!) as long as you keep a system based on dominant/recessive binary signals.

    But I agree that most ready-to-use implementation are based on standardised electrical conventions.

Comments are closed.