CAN Bus

Copied from a document here

### Purpose

This document will outline the high level goals and ideas behind a CAN bus as well as the low level technical implementation details for using one on the vehicle.

## Background & Idea

### Motivation

So you have a car with a bunch of controllers on it that want to send data to each other--how do they do it? Some common ways of doing this that you might already know are USB, Ethernet, WiFi, and Bluetooth, and some you may have heard of if you’ve taken some communication protocols courses are options like I2C, SPI, UART, UWB, etc. Those are all great, but each of them have their own benefits and drawbacks because they were all designed for particular use cases.

Our goal here is to let many different controllers that are far apart from each other in a really electrically noisy environment communicate with each other reliably as simply as possible. All the above solutions get knocked out by one of these criteria or another, be it I2C not supporting communication at distance or Bluetooth being unreliable (and complicated + power intensive) in noisy environments or otherwise, so we clearly need something different. This introduces us to CAN.

### Controller Area Network (CAN)

A Controller Area Network Bus, known as a CAN bus for short, is a hardware and software communication standard which allows for robust communication between many devices in a system (like a vehicle). This is the standard wired communication approach for automotive applications.

It does this on the physical layer with a singular pair of twisted wires (“high” and “low”) running along a common backbone with each device connected as a leaf to that backbone. See below:

## Hardware

### Physical Construction

CAN is composed of two wires--CAN high and CAN low. They are conventionally colored yellow for high and green for low, but that’s just a recommendation. These wires must be twisted together, known as a “twister pair” at all times. CAN must be constructed with a singular “backbone” which runs between all the devices on the bus. Every device on the bus, known as a “node”, should be connected via a branch coming off the main backbone.

Because this is a high speed communication signal, there are strict requirements about the maximum length of each of these parts of the physical construction of the bus. The total length of the backbone cannot exceed 40 meters from end to end. Additionally, each node off the bus cannot be greater than 12 inches from the main backbone. Below represents these requirements visually:

If any of these lengths are longer than the given specification, there is an exponentially increasing likelihood that the CAN bus will experience errors due to signal propagation delay or electrical interference.

Application Note: This node length also includes PCB traces, so if your CAN signal travels 3 inches from the connector to the CAN transceiver in the PCB, then you can only use <9 inches from the main backbone to that connector.

Clarification: These specifications are for the given CAN bus speed of 1Mbps. If you reduce the data rate of the bus to 500kbps or less, this will increase the tolerances for these requirements at the cost of increased bus data throughput.

The main backbone of the bus must have a 120 ohm terminating resistor on either end. It is strongly recommended to integrate these into the wiring harness directly rather than attempting to integrate them into the controllers on the bus.

It is worth noting here that, while other bus topologies do exist (star, ring, etc.), you should assume those are not allowed and not something to be considered if you are reading this document. The justifications for using those topologies are very complex and rare, and if you already know enough to know one of those topologies is right for you, then you probably wouldn’t be reading this document.

### Electrical Theory

CAN is highly redundant to electrical interference because it is a twisted differential pair. This means that, not only are the two “high” and “low” wires twisted together, but the data they are transmitting is encoded as the voltage difference between the two wires. In particular, if the bus is transmitting a 0 bit, both wires will be brought to 2.5V. If the bus is transmitting a 1, high will be brought to 3.5V and low will be brought to 1.5V. Rather than reading the actual voltages of each line individually, each controller just has to look at the voltage difference between high and low to determine if a 1 or a 0 is being sent.

This approach is so electrically redundant because, if there is electromagnetic interference which may affect the voltage present on one of the wires, it will affect both of the wires equally. Hence, even if high moves from 3.5V to 3.6V, low will equally shift from 1.5V to 1.6V, meaning their net difference will be maintained. This is unlike single-wire data communications like I2C where, given sufficient noise, a 0 could directly become a 1 or vice versa.

This also has the added benefit of making it possible for the bus to be electrically isolated from the other controllers, since it doesn’t matter if the two voltages are 100V and 102V as long as their differences are the same (within reason). This is also how 3.3V systems handle communicating on a CAN bus--they simply communicate at 3.3V and 1.3V and let the bus voltage be independent from their own voltage, letting them appear to be sending messages like every other controller.

The reasoning behind the strict length requirements comes from the speed of the bus directly--the bus is operating at such a fast rate that the time it takes for the voltage to change between individual bits becomes a very limiting factor. As the bus gets longer, not only does the capacitance increase (which increases the overall rise time), but the time it literally takes for the signal to travel from one end to the other becomes significant. To give some perspective (and this is very hand wavy), signals generally propagate at about 0.1C (one tenth the speed of light). That means it would take a signal about 1.3uS to travel 40m. If you now remember that we’re sending data at 1Mbps (one million bits per second), this means we’re sending one bit every 1uS. This means that, in the worst case, you could literally have one controller send the next bit of data before the furthest controller from it has even received the bit. This can obviously lead to issues where both controllers try to send data at the same time and because one thinks the other hasn’t started sending data yet when it actually has, which can result in a whole bunch of issues.

### PCBs

Keep the traces short and keep them far away from other high speed or high power traces. Generally a good practice for any communication protocol, and it’s a good practice here too. You have to be especially careful since they aren’t a twisted pair anymore, so you lose some of the electrical wizardry that was keeping us safe before.

### Controllers & Transceivers

Beyond the bus itself, a controller needs two components to be able to interact with the CAN bus: a controller and a transceiver. They are connected in the structure below:

The controller is the brains of the operation--it takes in basic data from the microcontroller like the message ID, header, payload, CRC, etc. and it loads it into a buffer to be transmitted. It will then attempt to transmit every message in the buffer in order when there are no other messages currently being transmitted on the bus. It similarly has a receive buffer where it takes in data from the bus and stores it for whenever the microcontroller wants to request it. It also automatically handles tasks like acknowledging, retrying, and arbitration directly in hardware without requiring any intervention from the microcontroller. It transmits the signals it wants as a series of binary 1s and 0s through CANTX to the transceiver to be translated into the differential signals the bus actually uses. It is similarly able to receive binary data directly via CANRX from the transceiver.

As was alluded to with the controller, the transceiver actually does the translation between the binary system voltages the microcontroller and CAN controller run at (probably 3.3) and the differential bus voltages.

While you can buy dedicated CAN controllers, they have been out of stock predominantly for the last few years due to the global parts shortage, so we mostly use microcontrollers which have integrated CAN controllers. The ESP32 has 1, the Teensy 4.0 has 2, and the Teensy 4.1 has 3. These do not come with transceivers, so those have to be included externally.

The main factor to consider when selecting a CAN transceiver is 1) that it supports you bus speed (probably 1Mbps) and 2) it is easy to implement. Avoid using transceivers which require all sorts of pins to be pulled to specific values with capacitors and resistors if possible--while these usually allow a greater degree of control and efficiency if you’re designing a part that will be used on 100k parts, it will take more time to set up the schematic correctly when you’re first designing with it, and it will be less likely to be interchangeable with a different CAN transceiver which may require you to tune its behavior in different ways.

## Software

If you skipped to this section, you should probably skim over the Controllers & Transceivers section.

Find our Git repo for CAN Bus code here.

### Packet Structure

As was mentioned in the intro, the CAN protocol calls out what exactly a CAN message, or “packet” should look like. The exact details aren’t super important since most of that will be abstracted away in code, but there are some key elements that you should be familiar with:

* Message ID
* Info / Control Field
* Data Payload
* CRC
* Acknowledge (ACK)

I’ll explain each of them below:

Message ID

Every message sent on CAN should have a unique message ID which it can be identified by. No two different messages should share the same ID, and no two controllers should ever send the same ID. Let’s say DAQ wants to always share the front right brake temperature on ID hex 670, then it should never send anything different on ID 670. You can encode multiple sensors into a single message, like say both the brake temperatures, but you shouldn’t randomly change the data to be different sensors in message 670, because you should just send those messages with different IDs. While selecting a CAN ID for your message is mostly arbitrary, it does have some consequences. See Arbitration for more details.

Control Field

Most of this is usually set for you automatically, but it contains information about the actual nature of the packet itself and the data payload it is carrying. For example, it can tell you how many bytes are in the payload, which can be useful to save time while processing incoming data.

Data Payload

This is the actual data you want to send from one controller to another. By default, CAN only supports data payloads of up to 8 bytes (64 bits). There are different versions of CAN which support larger payloads, but those generally don’t see widespread adoption in the hobby microcontroller space, so assume you’re limited to 8 bytes per message. You can also send less than 8 bytes of course, but the message ID, control fields, and CRC will remain the same size, so you’ll be making less efficient usage of the data being sent on the bus if you make your messages too short.

CRC

You will never have to calculate this. A CRC, or Cyclic Redundancy Check, is a set of bits which allows the receiving controller(s) to validate that the message they received contains the information that the other controller sent. The actual implementation of this is beyond the scope of this document, but you can trust that the data you’re receiving is correct since the controller will automatically throw out message which have an incorrect CRC.

Acknowledge (ACK)

Every time a CAN message is sent, every controller in unison “acknowledges” that the message was received. This is done automatically by the controller. Since a CAN bus with only one device is fundamentally useless, this confirms to the controller sending the data that there is at least one other device on the bus that is actually receiving that data properly. If the controller sends a message and does not receive an acknowledge, it will generally assume it made a mistake and retry. Some controllers are intelligent enough to make a certain number of retries before giving up and assuming the bus is not functional, but other controllers will continue trying indefinitely--if you are seeing no messages at all on your bus, try restarting it while you’re probing the bus and see if any messages come through that don’t get acknowledged.

Note: Because of this ACK feature, this also means a CAN device will not work if there is only one device on the bus. Some implementations will handle this gracefully, but others will literally hang at the function call to send the CAN message indefinitely as it continues retrying. If you see your code hanging on a CAN function call while testing, it may be due to it not being connected to any other devices. You can resolve this by connecting it to a dummy CAN device with a controller and transceiver which sends and receives no messages, but does have an initialized controller which can provide the ACKs.

### Arbitration

Generally each controller will attempt to wait until there are no messages being sent on the bus to send its own message. However, if two controllers both want to send a message at the same time and both wait until another message from a third controller finishes sending, then both controllers will attempt to send their messages at the same time. The CAN protocol handles this by making sure that every controller is both writing to and reading from the CAN bus at the same time. If it notices that the data it tried to send is not the same as the data it is seeing on the bus, it knows it has now entered arbitration with one or more other controllers. The message which will “win” arbitration and be allowed to send its data is the one with the lower message ID. Hence, if you have data which is very time critical, it should have a very low message ID, while messages which are less time-critical should have higher message IDs.

Application Note: Be careful when using messages with especially low IDs, as they can cause significant issues for the bus. For example, if a controller spams messages with an ID of 0, it will always win arbitration and no other messages will ever be sent. This can often happen by accident if someone simply puts a CAN message in a while loop without any form of timing restriction. For this reason, you should always gate your CAN messages behind some kind of timer or condition to ensure you do not overload the bus.

### Example

While this document may be a little redundant, there’s a full example for how to set up your own working CAN bus with the Teensy 4.0 with example code here.

### Advanced CAN Techniques

While the above document covers the basics for understanding and implementing a CAN bus, there are more advanced CAN techniques which can further improve the efficiency and effectiveness of the implementation while also further expanding the functionality that it offers. A few are listed below:

CAN Bus Bursting

Variable Override Routines (VORs)

CAN Bus Mailboxes