A Practical Intro to Controller Area Network
Learning the fundamentals and building a small CAN system
This is the first in a series on test & measurement automation using Flojoy and Controller Area Network (CAN) data.
Also see Part II: Building a CAN Data Logger for Test Monitoring
Preamble
If you already know everything about the CAN Protocol and just want to see a Flojoy Demo, see part two: Building a CAN data Logging for Test Monitoring.
I'm writing this series of articles for people who are new to the CAN Protocol and want to learn about it, but also for people wanting to interact with the protocol with Flojoy.
Some knowledge in electronics and programming may be required.
I'll be covering in this article:
What the CAN protocol is and why it's so important.
Some theory about it.
How we can to build a simple circuit.
Let's Get Started: What is the Controller Area Network and Why Is It So Important?
Before the existence of the Controller Area Network (CAN), cars had kilometers of wires running back and forth between the various devices in a vehicle. This not only proved to be expensive but also challenging to work with. The CAN protocol was developed to address this issue and is now utilized in virtually every car, truck, bus, tractor, and even ship and airplane.
The Controller Area Network solves this issue by introducing a message-based protocol primarily used for multiple microprocessors to communicate with each other on a single communication line in a robust and standardized manner.
In a car, the CAN bus system connects multiple electronic control units (ECUs) together. These ECUs are responsible for controlling the car's engine, transmission, airbags, and other systems, all of which need to transmit and receive data to and from each other. Instead of a multitude of wires running back and forth between the different devices in a car, a single CAN bus is employed to interconnect them. Each ECU can broadcast and receive messages, and it's up to them to decide how to react to the received information.
Understanding how to connect to this bus, and how to read and parse those messages, will enable you to diagnose issues and even control the car's systems if you know what you're doing.
This article will first help you understand this protocol, and later, we will construct a toy circuit to send and receive real CAN messages.
Some theory about the CAN bus Protocol
Data Link Layer
When you hear CAN, you should associate it with the Data Link Layer of the Open Systems Interconnection model, which describes the functional and procedural means of transferring data on the Physical Layer, the CAN bus wiring harness, as specified in ISO-11898-1.
Understanding the structure of a CAN frame is crucial for comprehending how information is transmitted within this protocol. From a "user" perspective, you will often see the following:
CAN ID Data bytes
0CF00400 FF FF FF 68 13 FF FF FFThis represents a list of bytes, symbolizing the data, and the ID of the senders. In reality, a standard frame contains a bit more information, as follows:
With:
SOF: Used to mark the Start Of the Frame.
Arbitration Field: The ID of the message, used to determine the priority of the message.
RTE: Remote Transmission Request, defining the frame type (Data Frame of Remote Frame).
Control Field: User-defined function, such as the length of the data.
Data Field: The transmitted data.
CRC: Cyclic Redundancy Check, used to check the integrity of the data.
ACK: Receiver's Acknowledgement.
EOF: End of Frame, used to mark the End Of the Frame.
A system node, such as the taillight, consists of several components, including a microcontroller housing the application logic, a CAN Controller responsible for transmitting messages from the microcontroller onto the bus when it is free, and a CAN transceiver, which is responsible for converting voltage levels on and off the bus.
The CAN Controller also plays a crucial role in storing received serial bits until the complete message is available. Subsequently, it triggers an interrupt in the microcontroller, allowing this one to retrieve the message.
Physical Layer
The physical layer, as specified in ISO-11898-2, describes the physical components on which the data link protocol is used. Some important aspects are:
An agreed
Baud rate, as not all devices share the same clock source which ensures synchronization between devices.The cable length, which limits the speed.
A 120-ohm bus termination at each end to absorb the signal. This is crucial to prevent signal reflection, which could otherwise occur and lead to signal distortion.
Before moving on to a real-world example, let's take a look at why CAN bus is so robust and reliable.
The reliability and robustness of the CAN bus are due to Differential Signalling, meaning the data is transmitted as the difference between two signals. This is why we use two wires, CAN_Low with a low voltage (1.5 - 2.5V), and CAN_High with a high voltage (2.5 - 3.5V), allowing the receiver to detect the difference between the two signals (CAN_H - CAN_L) and makes the signal more resilient to noise.
Another safety check comes from the use of cycle redundancy check to detect accidental changes in digital data, ensuring the integrity of the message.
The CAN FD Protocol
In addition to the traditional CAN protocol, there is the evolution known as CAN FD, which stands for Flexible Data-rate. The CAN FD protocol builds upon the classic CAN standard but introduces several enhancements to address the growing demands of modern applications.
Increased Data Rate: CAN FD allows for a higher data transfer rate compared to traditional CAN. This is particularly beneficial for applications requiring more extensive and faster data exchange.
Larger (and Flexible) Payload Size: One of the primary improvements is the ability to transmit larger data payloads in a single frame. This feature is crucial for applications where more information needs to be sent in a short amount of time.
Backward Compatibility: CAN FD maintains backward compatibility with the original CAN protocol. This means that CAN FD controllers can communicate with traditional CAN controllers, ensuring a smooth transition for existing systems.
With all that in mind, let's Build a Toy Circuit and send real CAN messages
For this, I'm using the following components:
Two Arduino
Two MCP2515 CAN Bus Interface Module.
Which includes the MCP2515 CAN controller and TJA1050 High speed CAN transceiver.
Some wires
Our first example will focus on transmitting a message from one node to another. This hands-on example will provide a practical understanding of how information flows between nodes within the CAN network and sets the stage for further exploration into real-world applications of the CAN protocol.
The Receiver:
In this scenario, the initial Arduino will serve as the receiver, tasked with listening to all messages on the CAN bus line. The received messages will be displayed by sending them to the monitor connected to the Serial port. This simple setup allows us to observe and monitor the communication flow between two nodes in our circuit.
#include <SPI.h>
// Library for using CAN Communication
// (https://github.com/autowp/arduino-mcp2515/)
#include <mcp2515.h>
struct can_frame canMsg;
MCP2515 mcp2515(10);
void setup() {
Serial.begin(9600);
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
Serial.println("------- CAN Read ----------");
Serial.println("ID DLC DATA");
}
void loop() {
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
Serial.print(canMsg.can_id, HEX);
Serial.print(" ");
Serial.print(canMsg.can_dlc, HEX);
Serial.print(" ");
// print the data (DLC: Data Length)
for (int i = 0; i < canMsg.can_dlc; i++) {
Serial.print(canMsg.data[i], HEX);
Serial.print(" ");
}
Serial.println();
}
}The Sender:
Now, let's shift our focus to the second Arduino, which will play the role of the sender in our two-node network. This Arduino is responsible for initiating the transmission of messages onto the CAN bus line. To demonstrate the transmission process, we'll craft a sample message and then transmit this message onto the CAN bus, where the receiver Arduino, as described earlier, will capture and display it.
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg;
MCP2515 mcp2515(10);
void setup()
{
while (!Serial);
Serial.begin(9600);
SPI.begin();
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
}
void loop()
{
canMsg.can_id = 0x002;
canMsg.can_dlc = 8;
canMsg.data[0] = 0x01;
canMsg.data[1] = 0x08;
canMsg.data[2] = 0x00;
canMsg.data[3] = 0x00;
canMsg.data[4] = 0x00;
canMsg.data[5] = 0x00;
canMsg.data[6] = 0x00;
canMsg.data[7] = 0x00;
mcp2515.sendMessage(&canMsg);
Serial.print("Data is on its way!!\n");
delay(1000);
}The Results:
Upon monitoring the Serial Connection of the receiver, we can observe all the sample messages sent by the sender. This successful communication between the nodes validates the functionality of our two-node network and demonstrates the seamless transmission and reception of CAN messages.




