My Cart

CAN Bus Module Tutorial for Arduino, Raspberry Pi and Intel Galileo

Difficulty Level: Intermediate -


CAN is a multi-master broadcast serial bus standard for connecting electronic control units (ECUs). Each node is able to send and receive messages, but not simultaneously. A message consists primarily of an ID (identifier), which represents the priority of the message. A CAN message that is transmitted with highest priority will succeed and the node transmitting the lower priority message will sense this and back off and wait.

The information is transmitted by two twisted wires that connect all system modules. It is transmitted by voltage difference between the two levels. The high voltage value represents 1 and low 0. Its combination forms an appropriate message.

CAN Bus
Standard ISO 11898
Cabling Twisted pair
Connector DB9
Network Topology Multimaster
Speed 125 to 1000 Kbps
Signaling Differential
Voltage Levels 0-5V
Signals Half Duplex

This list includes some of the more common uses of the standard:

  • Automotive applications
  • Home automation
  • Industrial Networking
  • Factory automation
  • Marine electronics
  • Medical equipment
  • Military uses

Get the shields

Kits

1. Features

The pack we are going to use in this tutorial includes the CAN Bus module and the Multiprotocol Radio Shield. The Multiprotocol Radio Shield can be used to connect two modules in order to combine the existing cooking-hacks modules and make connections between platforms. The CAN Bus module uses the SPI bus. The SPI port allows more speed communication and frees up the UART for other purposes like debugging or to connect communication modules.

Electrical Features

The CAN Bus module can be powered by the PC or by an external power supply. Some of the USB ports on computers are not able to give all the current the module needs to work, if your module have problems when it work, you can use an external power supply (12V - 2A) on the Arduino/Rasberry Pi/Intel Galileo.

2. The board

CAN Bus PCB

CAN Bus module over Arduino

The Multiprotocol Radio Shield has two sockets. The CAN Bus module must be connected as shown in the next figures. Please, see the Multiprotocol Radio Shield Tutorial for more information.

Get Arduino
Get the CAN Bus module
Get the Multiprotocol Radio Shield

CAN Bus over Raspberry Pi

Get Raspberry Pi
Get the Raspberry Pi to Arduino shields connection bridge
Get the CAN Bus module
Warnings:
  • The CAN Bus module must be connected in the corresponding socket as shown in this tutorial.
  • The CAN Bus module is not compatible with the XBee shield. You have to use the Multiprotocol Radio Shield as shown in this tutorial.
  • The CAN Bus module has been tested with several devices, but we don't ensure the compatibility with all commercial devices.

3. The Library

The CAN Bus module counts with a C++ library that lets you manage the CAN Bus module in a simple way. This library offers an simple-to-use open source system.

In order to ensure the same code is compatible in both platforms (Arduino, Raspberry Pi and Intel Galileo) we use the ArduPi libraries which allows developers to use the same code. Detailed info can be found here:

Using the library with Arduino

The CAN Bus module includes a high level library functions for a easy manage. Before start using this functions you should download the files from the next link. This zip includes all the files needed in several folders. These folders include the necessary file for using CAN Bus protocol.

Download the CAN Bus library for Arduino.

Libraries are often distributed as a ZIP file or folder. The name of the folder is the name of the library. Inside the folder will be the .cpp files, .h files and a examples folder.

To install the library, first quit the Arduino application. Then uncompress the ZIP file containing the library. For installing libraries, uncompress zip file. Drag these folders into your libraries folder. Under Windows, it will likely be called "My Documents\Arduino\libraries". For Mac users, it will likely be called "Documents/Arduino/libraries". On Linux, it will be the "libraries" folder in your sketchbook.

The library won't work if you put the .cpp and .h files directly into the libraries folder or if they're tested in an extra folder. Restart the Arduino application. Make sure the new library appears in the Sketch->Import Library menu item of the software.

Using the library with Raspberry Pi

The CAN Bus library for Raspberry Pi requires the ArduPi library and both libraries should be in the same path.

Download the CAN Bus library for Raspberry Pi.

wget http://www.cooking-hacks.com/media/cooking/images/documentation/CANBus/arduPi-api_CANBUS_v0_2.zip && unzip arduPi-api_CANBUS_v0_2.zip && cd cooking/examples/CANBUS && chmod +x cook.sh && cd ../../.. 

Creating a program that uses the library is as simple as putting your code in this template where it says "your Arduino code here"

Code:
//Include CAN Bus library (it includes arduPi)


/********************************************************
*  IF YOUR ARDUINO CODE HAS OTHER FUNCTIONS APART FROM  *
*  setup() AND loop() YOU MUST DECLARE THEM HERE        *
* *******************************************************/

/*************************
* YOUR ARDUINO CODE HERE *
* ************************/

int main (){
  setup();
  while(1){
    loop();
  }
  return(0);
}
    

Follow the next steps to compile a sketch:

  • First, install ArduPi and CAN Bus libraries.
    • ArduPi For Raspberry Pi:

      wget http://www.cooking-hacks.com/media/cooking/images/documentation/raspberry_arduino_shield/raspberrypi.zip && unzip raspberrypi.zip && cd cooking/arduPi && chmod +x install_arduPi && ./install_arduPi && rm install_arduPi && cd ../..
      		

      ArduPi For Raspberry Pi 2:

      wget http://www.cooking-hacks.com/media/cooking/images/documentation/raspberry_arduino_shield/raspberrypi2.zip && unzip raspberrypi2.zip && cd cooking/arduPi && chmod +x install_arduPi && ./install_arduPi && rm install_arduPi && cd ../..
      		

      CAN Bus Library:

      wget http://www.cooking-hacks.com/media/cooking/images/documentation/CANBus/arduPi-api_CANBUS_v0_2.zip && unzip arduPi-api_CANBUS_v0_2.zip && cd cooking/examples/CANBUS && chmod +x cook.sh && cd ../../.. 
      
  • Go to examples:
    • cd cooking/examples/CANBUS/ 
      
  • Compile the example:
    • ./cook.sh my_example.cpp 
      
  • Run the sketch:
    • ./my_example.cpp_exe 
      

The script "cook.sh" compiles everything in their folders and the link in the examples foldes with the "_exe" executable.

  • Help: ./cook.sh
  • Clean: ./cook.sh -clean (It deletes all the "*.o" files. This is only necessary if you make changes in the libraries)

Using the library with Intel Galileo

The CAN Bus module includes a high level library functions for a easy manage. Before start using this functions you should download the files from the next link. This zip includes all the files needed in several folders. These folders include the necessary file for using CAN Bus protocol.

Download the CAN Bus library for Intel Galileo

Libraries are often distributed as a ZIP file or folder. The name of the folder is the name of the library. Inside the folder will be the .cpp files, .h files and often a keywords.txt file, examples folder, and other files required by the library.

To install the library, first quit the Arduino application. Then uncompress the ZIP file containing the library. For installing libraries , uncompress zip file. It should contain three folder called CANBUS. Drag these folders into this folder (your libraries folder). Under Windows, it will likely be called "My Documents\Arduino\libraries". For Mac users, it will likely be called "Documents/Arduino/libraries". On Linux, it will be the "libraries" folder in your sketchbook.

The library won't work if you put the .cpp and .h files directly into the libraries folder or if they're nested in an extra folder. Restart the Arduino application. Make sure the new library appears in the Sketch->Import Library menu item of the software.

General CAN Bus functions

General functions

  // Receive buffer
  messageCAN messageRx;
  // Trasmit buffer
  messageCAN messageTx;

  // Powers the CAN Bus module and opens the SPI
  bool begin(uint16_t speed);
  // Check if there is any message
  uint8_t messageAvailable(void);
  // Take the CAN message
  char getMessage(messageCAN *msje);
  // Send the CAN message
  char sendMessage(messageCAN *msje);
  // CAN message print out the serial port
  void printMessage(messageCAN *msje);
  // Configure the MCP2515
  void setMode(uint8_t mode);

CAN in Automation (CiA)

  unsigned int getEngineLoad();
  unsigned int getEngineCoolantTemp();
  unsigned int getFuelPressure();
  unsigned int getIntakeMAPressure();
  unsigned int getEngineRPM();
  unsigned int getVehicleSpeed();
  unsigned int getTimingAdvance();
  unsigned int getIntankeAirTemp();
  unsigned int getMAFairFlowRate();
  unsigned int getThrottlePosition();
  unsigned int getFuelLevel();
  unsigned int getBarometricPressure();
  unsigned int getEngineFuelRate();

4. Connecting Devices

Sending data using the CAN Bus module

Materials:

1. Connect the Multiprotocol Radio Shield over the Arduino UNO and the CAN Bus module as shown in the figure.

2. The CAN Bus module can be used to send data between devices to create a communications network. This network. CAN Bus is a multi-master broadcast serial bus standard. Each node is able to send and receive messages and the identification of the node must be done in the code. Every message will include the direction of the device and all the devices will receive all messages. The ID of each node must be unique in the network, otherwise two nodes would continue transmission beyond the end of the arbitration field causing an error.

Note: The wire used in this part of the tutorial is a male-male DB9

3. In your serial monitor you should receive data. In this code, all messages are printed but you can program your Arduino to filtering messages.

Arduino / Intel Galileo

Code:
/*  
 *  CAN Bus Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  a
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Ahmad Saad & Luis Martin
 */

// Include always these libraries before using the CAN BUS functions
#include <CAN.h>
#include <SPI.h>

// ID numbers
#define IDWAITED 200
#define OWNID 100

// Create an instance of the object
CAN myCAN = CAN();

// Setting up our devices and I/Os
void setup() {
  // Initializes the UART
  Serial.begin(115200);
  delay(100);

  // Let's open the bus. Remember the input parameter:
  // 1: 1Mbps
  // 500: 500Kbps  <--- Most frequently used
  // 250: 250Kbp
  // 125: 125Kbps
  myCAN.begin(125);
}

void loop() {
  
  //****************************************
  // 1. Receive data
  //****************************************
  
  if (myCAN.messageAvailable() == 1) {
    // Read the last message received.
    myCAN.getMessage(&myCAN.messageRx);
    // Print in the serial monitor the received message
    myCAN.printMessage(&myCAN.messageRx);
  }
  

  //****************************************
  // 2. Send data
  //****************************************
  
  // Insert the ID in the data structure
  myCAN.messageTx.id = OWNID;
  // These fields include the data to send
  myCAN.messageTx.data[0] = 0;
  myCAN.messageTx.data[1] += 1;
  myCAN.messageTx.data[2] = 2;
  myCAN.messageTx.data[3] = 3;
  myCAN.messageTx.data[4] = 4;
  myCAN.messageTx.data[5] = 5;
  myCAN.messageTx.data[6] = 6;
  myCAN.messageTx.data[7] = 7;

  // The length of the data structure
  myCAN.messageTx.header.length = 8;
  // Send data
  myCAN.sendMessage(&myCAN.messageTx);  
  // A time delay
  delay(1000);
}
    

Raspberry Pi

Code:
/*  
 *  CAN Bus Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  a
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Ahmad Saad & Luis MartĂ­n
 */

// Include always these libraries before using the CAN BUS functions
#include "CAN.h"
#include "arduPi.h"

// ID numbers
#define IDWAITED 200
#define OWNID 100

// Create an instance of the object
CAN myCAN = CAN();

// Setting up our devices and I/Os
void setup() {
  

  // Let's open the bus. Remember the input parameter:
  // 1: 1Mbps
  // 500: 500Kbps  <--- Most frequently used
  // 250: 250Kbp
  // 125: 125Kbps
  myCAN.begin(1000);
}

void loop() {
  
  //****************************************
  // 1. Receive data
  //****************************************
  
  if (myCAN.messageAvailable() == 1) {
    // Read the last message received.
    myCAN.getMessage(&myCAN.messageRx);
    // Print in the serial monitor the received message
    myCAN.printMessage(&myCAN.messageRx);
  }
  

  //****************************************
  // 2. Send data
  //****************************************
  
  // Insert the ID in the data structure
  myCAN.messageTx.id = OWNID;
  // These fields include the data to send
  myCAN.messageTx.data[0] = 0;
  myCAN.messageTx.data[1] += 1;
  myCAN.messageTx.data[2] = 2;
  myCAN.messageTx.data[3] = 3;
  myCAN.messageTx.data[4] = 4;
  myCAN.messageTx.data[5] = 5;
  myCAN.messageTx.data[6] = 6;
  myCAN.messageTx.data[7] = 7;

  // The length of the data structure
  myCAN.messageTx.header.length = 8;
  // Send data
  myCAN.sendMessage(&myCAN.messageTx);  
  // A time delay
  delay(1000);
}

int main (){
  setup();
  while(1){
    loop();
  }
  return (0);
}

    

CAN in Automation (CiA)

The OBD-II standard has been mandatory for all cars and light trucks sold in the United States since 1996, and the EOBD standard has been mandatory for all petrol vehicles sold in the European Union since 2001 and all diesel vehicles since 2004. The car manufactures usually protect the access to the CAN Bus of the vehicle, so sometimes is not possible to get data directly by connecting the CAN Bus module to the OBD-II connector of the car. The user must consult how to connect the CAN Bus module to the device or car.


Signal Ground 1 5
Chassis Ground 2 4
CAN High (J-2284) 3 6
ISO 9141-2 K Line       4 7
CAN Low (J-2284) 5 14
J1850 Bus - 6 10
J1850 Bus + 7 2
ISO 9141-2 L Line 8 15
Battery Power 9 16

The OBD-II specification provides for a standardized hardware interface-the female 16-pin (2x8) J1962 connector. Unlike others connectors, which was sometimes found under the hood of the vehicle, the OBD-II connector is required to be within 2 feet (0.61m) of the steering wheel (unless an exemption is applied for by the manufacturer, in which case it is still somewhere within reach of the driver).

This cable allows the user to access the pins on a car's OBD-II connector. It has an OBD-II connector on one end and a DB9 male serial connector on the other.

Arduino / Intel Galileo

Code:
/*  
 *  CAN Bus Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  a
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Ahmad Saad & Luis Antonio
 */
 
// Include always these libraries before using the CAN BUS functions 
#include <CAN.h> 
#include <SPI.h> 

// Create an instance 
CAN myCAN = CAN(); 

void setup() 
{    
  // Inits the UART 
  Serial.begin(115200); 
  delay(100); 
  
  // Print init message 
  Serial.println("Initializing CANBUS...");  
  
  // Configuring the BUS at 500 Kbit/s 
  myCAN.begin(500);   
    
  Serial.println("CANBUS initialized at 500 KBits/s");  
} 

void loop() 
{ 
  // Read the value of RPM if the engine   
  long engineRpm = myCAN.getEngineRPM();      

  // Print received data in the serial monitor 
  Serial.print("RPM of engine : "); 
  Serial.println(engineRpm); 
  delay(1000); 
} 
    

Raspberry Pi

Code:
/*  
 *  CAN Bus Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  a
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Ahmad Saad & Luis MartĂ­n
 */
 
// Include always these libraries before using the CAN BUS functions
#include "CAN.h"
#include "arduPi.h"

// Create an instance
CAN myCAN = CAN();

void setup()
{   
  // Inits the UART
  Serial.begin(115200);
  delay(100);
  
  // Print init message 
  printf("Initializing CANBUS...\n"); 
  
  // Configuring the BUS at 500 Kbit/s
  myCAN.begin(500);   
    
  printf("CANBUS initialized at 500 KBits/s\n");  
}

void loop()
{
  // Read the value of RPM if the engine  
  int engineRpm = myCAN.getEngineRPM();      

  // Print received data in the serial monitor
  printf("RPM of engine : %d",engineRpm); 
  printf("\n");
  delay(1000); 
}

int main (){
  setup();
  while(1){
    loop();
  }
  return (0);
}
    

You should receive the data in your serial monitor.

Dual protocol connection with Multriprotocol Radio Shield

The Multiprotocol Radio Shield can be used to connect two communication protocols at the same time and make interconnections between different systems and devices. In the next example we are going to interconnect a CAN Bus module with wireless protocol using and XBee module.

NOTE:

  • In AP=0 all data send trough the UART will be send by the XBee module.
  • The XBee 802.15.4 modules must be connected using external pins. These pins must have the pin 4 of the XBee cut or disconnected to avoid interferences between modules.

Connect the CAN Bus module and XBee modules in the corresponding sockets as shown in the next image:

If you are using 802.15.4, use external pin with pin4 disconnected.

You should receive all data in your gateway device


Code:
/*  
 *  CAN Bus Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  a
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Ahmad Saad & Luis MartĂ­n
 */
 
// Include always these libraries before using the CAN BUS functions 
#include <CAN.h> 
#include <SPI.h> 

// Create an instance 
CAN myCAN = CAN(); 

void setup() 
{    
  // Inits the UART 
  Serial.begin(9600); 
  delay(100); 
  
  pinMode(5, OUTPUT);
  digitalWrite(5, HIGH);
  
  // Print init message 
  Serial.println("Initializing CANBUS...");  
  
  // Configuring the BUS at 500 Kbit/s 
  myCAN.begin(500);   
    
  Serial.println("CANBUS initialized at 500 KBits/s");  
} 

void loop() 
{ 
  // Read the value of RPM if the engine   
  long engineRpm = myCAN.getEngineRPM();      

  // Print received data in the serial monitor 
  Serial.print("RPM of engine : "); 
  Serial.println(engineRpm); 
  delay(1000); 
} 
    

Device Compatibility

This shield is tested and fully compatible with the following boards:

Arduino Boards

  • Arduino Uno

Raspberry Pi Boards

  • Raspberry Pi
  • Raspberry Pi (Model B+)
  • Raspberry Pi 2
  • Raspberry Pi 3