In this tutorial I am going to show you how to interface the MCP2515 CAN Bus Controller with an Arduino and how to communicate between two Arduinos via CAN BUS.
This tutorial can be a good kickstart for the future development of an individual CAN writer or reader to use it in different applications (car CAN Bus sniffer, connection to an equipment control network, among others).
Parts Required
- Two Arduinos (any version);
- Two MCP2515 interface boards;
- Jumper wires.
MCP2515 Can Controller + TJA1050 Can Transceiver
The MCP2515 CAN Bus Controller it’s an IC that supports CAN Protocol version 2.0 and can be used for communication at 1Mbps.
This particular module is based on the MCP2515 CAN Controller IC and the TJA1050 CAN Transceiver IC. The MCP2515 IC is a standalone CAN Controller and has an integrated SPI Interface for communication with microcontrollers.
MCP2515 IC is the main controller that internally consists of three main subcomponents: The CAN Module (responsible for transmitting and receiving messages on the CAN Bus), the Control Logic (handles the setup and operation of the MCP2515 by interfacing all the blocks) and the SPI Block (responsible for the SPI communication interface).
The TJA1050 IC acts as an interface between the MCP2515 CAN Controller IC and the Physical CAN Bus. Since it acts as an interface between MCP2515 CAN Controller and the physical CAN Bus, this IC is responsible for taking the data from the controller and relaying it on to the bus.
Circuit
Arduino Pin | CAN Board Pin |
10 | CS |
11 | SI |
12 | SO |
13 | SCK |
CAN Board 1 Pin | CAN Board 2 Pin |
CAN H | CAN H |
CAN L | CAN L |
One Arduino Uno and one Arduino Micro were used in this project, but you can use the version of the Arduino that you have, as long as the connections for MISO, MOSI, CS and SCK are fulfilled.
Code
It is necessary to install a library for the MCP2515 Module. In this project we used this particular one. Here is a guide to install .zip libraries.
Transmitter Code
#include <SPI.h> #include <mcp2515.h>struct can_frame canMsg1; struct can_frame canMsg2; MCP2515 mcp2515(10); void setup() { canMsg1.can_id = 0x0F6; canMsg1.can_dlc = 8; canMsg1.data[0] = 0x8E; canMsg1.data[1] = 0x87; canMsg1.data[2] = 0x32; canMsg1.data[3] = 0xFA; canMsg1.data[4] = 0x26; canMsg1.data[5] = 0x8E; canMsg1.data[6] = 0xBE; canMsg1.data[7] = 0x86; Serial.begin(115200); mcp2515.reset(); mcp2515.setBitrate(CAN_125KBPS); mcp2515.setNormalMode(); Serial.println("Example: Write to CAN"); } void loop() { mcp2515.sendMessage(&canMsg1); Serial.println("Messages sent"); delay(100); }
Receiver Code
#include <SPI.h> #include <mcp2515.h> struct can_frame canMsg; MCP2515 mcp2515(10); void setup() { Serial.begin(115200); mcp2515.reset(); mcp2515.setBitrate(CAN_125KBPS); 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); // print ID Serial.print(" "); Serial.print(canMsg.can_dlc, HEX); // print DLC Serial.print(" "); for (int i = 0; i<canMsg.can_dlc; i++) { // print the data Serial.print(canMsg.data[i],DEC); Serial.print(" "); } Serial.println(); } }
Results
Here we are visualizing the data in decimal format, but if you want to see it in hexadecimal, change DEC to HEX in line 29 of the receiver code.
References
[1] https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Stand-Alone-CAN-Controller-with-SPI-20001801J.pdf
[2] https://www.nxp.com/docs/en/data-sheet/TJA1050.pdf?
[3] https://www.electronicshub.org/arduino-mcp2515-can-bus-tutorial/
[4] https://circuitdigest.com/microcontroller-projects/arduino-can-tutorial-interfacing-mcp2515-can-bus-module-with-arduino