Arduino library for the MCP2515 CAN Controller

MCP2515 CAN Controller Library for Arduino

Compatibility with the ACAN library

This library is fully compatible with the Teensy 3.x ACAN library https://github.com/pierremolinaro/acan, ACAN2515 library https://github.com/pierremolinaro/acan2515, ACAN2517 library https://github.com/pierremolinaro/acan2517, it uses a very similar API and the same CANMessage class for handling messages.

ACAN2515Tiny library description

It is an adaptation of ACAN2515 library in order to reduce the memory footprint.

ACAN2515Tiny is a driver for the MCP2515 CAN Controller. It runs on any Arduino compatible board.

You can choose any frequency for your MCP2515, the actual frequency is a parameter of the library.

The driver supports many bit rates: for a 16 MHz quartz, the CAN bit timing calculator finds settings for standard 62.5 kbit/s, 125 kbit/s, 250 kbit/s, 500 kbit/s, 1 Mbit/s, but also for an exotic bit rate as 727 kbit/s. If the desired bit rate cannot be achieved, the begin method does not configure the hardware and returns an error code.

Driver API is fully described by the PDF file in the extras directory.

Demo Sketch

The demo sketch is in the examples/TinyLoopBackDemo directory.

Configuration is a four-step operation.

  1. Instanciation of the settings object : the constructor has one parameter: the wished CAN bit rate. The settings is fully initialized.
  2. You can override default settings. Here, we set the mRequestedMode property to true, enabling to run demo code without any additional hardware (no CAN transceiver needed). We can also for example change the receive buffer size by setting the mReceiveBufferSize property.
  3. Calling the begin method configures the driver and starts CAN bus participation. Any message can be sent, any frame on the bus is received. No default filter to provide.
  4. You check the errorCode value to detect configuration error(s).
static const byte MCP2515_CS  = 20 ; // CS input of MCP2515, adapt to your design
static const byte MCP2515_INT = 37 ; // INT output of MCP2515, adapt to your design

ACAN2515Tiny can (MCP2515_CS, SPI, MCP2515_INT) ; // You can use SPI2, SPI3, if provided by your microcontroller

const uint32_t QUARTZ_FREQUENCY = 16 * 1000 * 1000 ; // 16 MHz

void setup () {
  Serial.begin (9600) ;
  while (!Serial) {}
  Serial.println ("Hello") ;
  ACAN2515TinySettings settings (QUARTZ_FREQUENCY, 125 * 1000) ; // 125 kbit/s
  settings.mRequestedMode = ACAN2515TinySettings::LoopBackMode ; // Select loopback mode
  const uint16_t errorCode = can.begin (settings, [] { can.isr () ; }) ;
  if (0 == errorCode) {
    Serial.println ("Can ok") ;
  }else{
    Serial.print ("Error Can: 0x") ;
    Serial.println (errorCode, HEX) ;
  }
}

Now, an example of the loop function. As we have selected loop back mode, every sent frame is received.

static uint32_t gSendDate = 0 ;
static uint32_t gSentCount = 0 ;
static uint32_t gReceivedCount = 0 ;

void loop () {
  CANMessage message ;
  if (gSendDate < millis ()) {
    message.id = 0x542 ;
    const bool ok = can.tryToSend (message) ;
    if (ok) {
      gSendDate += 2000 ;
      gSentCount += 1 ;
      Serial.print ("Sent: ") ;
      Serial.println (gSentCount) ;
    }
  }
  if (can.receive (message)) {
    gReceivedCount += 1 ;
    Serial.print ("Received: ") ;
    Serial.println (gReceivedCount) ;
  }
}

CANMessage is the class that defines a CAN message. The message object is fully initialized by the default constructor. Here, we set the id to 0x542 for sending a standard data frame, without data, with this identifier.

The can.tryToSend tries to send the message. It returns true if the message has been sucessfully added to the driver transmit buffer.

The gSendDate variable handles sending a CAN message every 2000 ms.

can.receive returns true if a message has been received, and assigned to the messageargument.

Use of Optional Reception Filtering

The MCP2515 CAN Controller implements two acceptance masks and six acceptance filters. The driver API enables you to fully manage these registers.

For example (loopbackUsingFilters sketch):

  ACAN2515TinySettings settings (QUARTZ_FREQUENCY, 125 * 1000) ;
  settings.mRequestedMode = ACAN2515TinySettings::LoopBackMode ; // Select loopback mode
  const ACAN2515Mask rxm0 = extended2515Mask (0x1FFFFFFF) ; // For filter #0 and #1
  const ACAN2515Mask rxm1 = standard2515Mask (0x7F0, 0xFF, 0) ; // For filter #2 to #5
  const ACAN2515AcceptanceFilter filters [] = {
    {extended2515Filter (0x12345678), receive0},
    {extended2515Filter (0x18765432), receive1},
    {standard2515Filter (0x560, 0x55, 0), receive2}
  } ;
  const uint16_t errorCode = can.begin (settings, [] { can.isr () ; }, rxm0, rxm1, filters, 3) ;

These settings enable the acceptance of extended frames whose identifier is 0x12345678 or 0x18765432, and data frames whose identifier is 0x560 and first data byte, if any, is 0x55.

The receive0, receive1, receive2 functions are call back functions, handled by the can.dispatchReceivedMessage function:

void loop () {
  can.dispatchReceivedMessage () ; // Do not use can.receive any more
  ...
}
Similar Resources

The Approximate Library is a WiFi Arduino library for building proximate interactions between your Internet of Things and the ESP8266 or ESP32

The Approximate Library is a WiFi Arduino library for building proximate interactions between your Internet of Things and the ESP8266 or ESP32

The Approximate Library The Approximate library is a WiFi Arduino Library for building proximate interactions between your Internet of Things and the

Dec 7, 2022

An ESP32 CAN 2.0B library

CAN Library for ESP32 ACAN_ESP32 library description ACAN_ESP32 is a driver for the CAN module built into the ESP32 microcontroller. The driver suppor

Dec 9, 2022

Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages.

Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages.

107-Arduino-NMEA-Parser Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages. This library

Jan 1, 2023

Arduino library for providing a convenient C++ interface for accessing UAVCAN.

Arduino library for providing a convenient C++ interface for accessing UAVCAN.

107-Arduino-UAVCAN Arduino library for providing a convenient C++ interface for accessing UAVCAN (v1.0-beta) utilizing libcanard. This library works f

Jan 2, 2023

Arduino web server library.

aWOT Arduino web server library. Documentation 1. Getting started Hello World Basic routing Application generator Serving static files 2. Guide Routin

Jan 4, 2023

Arduino, esp32 and esp8266 library for ABB (ex PowerOne) Aurora Inverter, implement a full methods to retrieve data from the Inverter via RS-485

Arduino, esp32 and esp8266 library for ABB (ex PowerOne) Aurora Inverter, implement a full methods to retrieve data from the Inverter via RS-485

ABB Aurora protocol You can refer the complete documentation on my site ABB Aurora PV inverter library for Arduino, esp8266 and esp32 I create this li

Nov 22, 2022

Analog Devices Analog Digital Converter AD7173 Arduino library

AD7173-Arduino Analog Devices AD7173 analog digital converter Arduino library Mostly tested setup for this library: 1007 data rate external crystal co

Nov 20, 2022

Arduino library for nRF51822-based Adafruit Bluefruit LE modules

This library is for all nRF51 based Adafruit Bluefruit LE modules that use SPI or UART. Current nRF51 based Bluefruit LE products include: Bluefruit L

Nov 6, 2022

Arduino library for the Adafruit FONA

Adafruit FONA Library This library requires Arduino v1.0.6 or higher This is a library for the Adafruit FONA Cellular GSM Breakouts etc Designed speci

Dec 15, 2022
Comments
  • It seems like CANMessage::id is not 32bit

    It seems like CANMessage::id is not 32bit

    It looks like the effective bit depth of CANMessage::id is not 32-bit. The following pseudo-code fails:

    send() { CANMessage message; message.id = deviceID << 16; //deviceID is in the range [1;0xff] message.id |= command; //command < 0xffff trytosend(); }

    receive() { CANMessage message; can.receive(message);

    println(message.id); //prints 'command', e.g. the high word value is lost }

    If I shift deviceID for 8 bits, e.g. 'message.id = deviceID << 8;' and make sure command is in the range [0;0xff] everthing works fine.

  • Use correct field separator in keywords.txt

    Use correct field separator in keywords.txt

    The Arduino IDE requires the use of a single true tab separator between the keyword name and identifier. When spaces are used rather than a true tab, the keyword is not highlighted.

    Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords

  • Multiple instantiation of the can object

    Multiple instantiation of the can object

    Hello Pierre, I'm trying to connect two 2515 boards to my Arduino (Mega2560). I defined 2 different chip selects and interrupts (10/3 & 11/2) and taken separately they work. When I try to instantiate 2 can objects (can0, can1 with 2 settings objects), the 2nd one gives an error on can1.begin.

    Thanks in advance for your help Claude

    This is the setup function adapted from your sample code: static const byte MCP2515_CS0 = 10 ; // CS input of MCP2515 (adapt to your design) static const byte MCP2515_INT0 = 3 ; // INT output of MCP2515 (adapt to your design)

    static const byte MCP2515_CS1 = 11 ; // CS input of MCP2515 (adapt to your design) static const byte MCP2515_INT1 = 2 ; // INT output of MCP2515 (adapt to your design)

    //—————————————————————————————————————————————————————————————————————————————— // MCP2515 Driver object //——————————————————————————————————————————————————————————————————————————————

    ACAN2515Tiny can0 (MCP2515_CS0, SPI, MCP2515_INT0) ; ACAN2515Tiny can1 (MCP2515_CS1, SPI, MCP2515_INT1) ;

    //—————————————————————————————————————————————————————————————————————————————— // MCP2515 Quartz: adapt to your design //——————————————————————————————————————————————————————————————————————————————

    static const uint32_t QUARTZ_FREQUENCY = 8UL * 1000UL * 1000UL ; // 16 MHz

    //—————————————————————————————————————————————————————————————————————————————— // SETUP //——————————————————————————————————————————————————————————————————————————————

    void setup () { //--- Switch on builtin led pinMode (LED_BUILTIN, OUTPUT) ; digitalWrite (LED_BUILTIN, HIGH) ; //--- Start serial Serial.begin (38400) ; //--- Wait for serial (blink led at 10 Hz during waiting) while (!Serial) { delay (50) ; digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ; } //--- Begin SPI SPI.begin () ; //--- Configure ACAN2515 Serial.println ("Configure ACAN2515_0") ; ACAN2515TinySettings settings0 (QUARTZ_FREQUENCY, 500UL * 1000UL) ; // CAN bit rate 500 kb/s // settings0.mRequestedMode = ACAN2515TinySettings::LoopBackMode ; // Select loopback mode settings0.mRequestedMode = ACAN2515TinySettings::NormalMode ; const uint16_t errorCode0 = can0.begin (settings0, [] { can0.isr () ; }) ; if (errorCode0 == 0) { Serial.print ("Bit Rate prescaler: ") ; Serial.println (settings0.mBitRatePrescaler) ; Serial.print ("Propagation Segment: ") ; Serial.println (settings0.mPropagationSegment) ; Serial.print ("Phase segment 1: ") ; Serial.println (settings0.mPhaseSegment1) ; Serial.print ("Phase segment 2: ") ; Serial.println (settings0.mPhaseSegment2) ; Serial.print ("SJW: ") ; Serial.println (settings0.mSJW) ; Serial.print ("Triple Sampling: ") ; Serial.println (settings0.mTripleSampling ? "yes" : "no") ; Serial.print ("Actual bit rate: ") ; Serial.print (settings0.actualBitRate ()) ; Serial.println (" bit/s") ; Serial.print ("Exact bit rate ? ") ; Serial.println (settings0.exactBitRate () ? "yes" : "no") ; Serial.print ("Sample point: ") ; Serial.print (settings0.samplePointFromBitStart ()) ; Serial.println ("%") ; }else{ Serial.print ("Configuration error 0x") ; Serial.println (errorCode0, HEX) ; }

    Serial.println ("Configure ACAN2515_1") ; ACAN2515TinySettings settings1 (QUARTZ_FREQUENCY, 500UL * 1000UL) ; // CAN bit rate 500 kb/s settings1.mRequestedMode = ACAN2515TinySettings::LoopBackMode ; // Select loopback mode //settings1.mRequestedMode = ACAN2515TinySettings::NormalMode ; const uint16_t errorCode1 = can1.begin (settings1, [] { can1.isr () ; }) ; if (errorCode1 == 0) { Serial.print ("Bit Rate prescaler: ") ; Serial.println (settings1.mBitRatePrescaler) ; Serial.print ("Propagation Segment: ") ; Serial.println (settings1.mPropagationSegment) ; Serial.print ("Phase segment 1: ") ; Serial.println (settings1.mPhaseSegment1) ; Serial.print ("Phase segment 2: ") ; Serial.println (settings1.mPhaseSegment2) ; Serial.print ("SJW: ") ; Serial.println (settings1.mSJW) ; Serial.print ("Triple Sampling: ") ; Serial.println (settings1.mTripleSampling ? "yes" : "no") ; Serial.print ("Actual bit rate: ") ; Serial.print (settings1.actualBitRate ()) ; Serial.println (" bit/s") ; Serial.print ("Exact bit rate ? ") ; Serial.println (settings1.exactBitRate () ? "yes" : "no") ; Serial.print ("Sample point: ") ; Serial.print (settings1.samplePointFromBitStart ()) ; Serial.println ("%") ; }else{ Serial.print ("Configuration error 0x") ; Serial.println (errorCode1, HEX) ; } }

  • The MCP2515

    The MCP2515 "READ RX BUFFER" instruction automatically clears the associated receive flag in CANINTF

    According to the MCP2515 data sheet (DS20001801J-page 65, 12.4 READ RX BUFFER Instruction):

    This instruction further reduces the SPI overhead by automatically clearing the associated receive flag, RXnIF (CANINTF), when CS is raised at the end of the command.

    As void ACAN2515Tiny::handleRXBInterrupt (void) uses this instruction:

    mSPI.transfer (accessRXB0 ? READ_FROM_RXB0SIDH_COMMAND : READ_FROM_RXB1SIDH_COMMAND) ;
    

    this doesn't seems necessary:

    //--- Free receive buffer command
    bitModify2515Register (CANINTF_REGISTER, accessRXB0 ? 0x01 : 0x02, 0) ;
    
Related tags
Arduino library for controlling the MCP2515 in order to receive/transmit CAN frames.
Arduino library for controlling the MCP2515 in order to receive/transmit CAN frames.

107-Arduino-MCP2515 Arduino library for controlling the MCP2515 in order to receive/transmit CAN frames. This library is prepared to interface easily

Nov 16, 2022
Arduino CAN driver for MCP2517FD CAN Controller (in CAN 2.0B mode)

MCP2517FD CAN Controller Library for Arduino (in CAN 2.0B mode) Compatibility with the other ACAN libraries This library is fully compatible with the

Dec 22, 2022
Distribution of Arduino driver for MCP2517FD CAN controller (CANFD mode)

MCP2517FD and MCP2518FD CAN Controller Library for Arduino (in CAN FD mode) Compatibility with the other ACAN libraries This library is fully compatib

Dec 21, 2022
Unified interface for selecting different implementations for communicating with a TM1637 LED controller chip on Arduino platforms

AceTMI Unified interface for communicating with a TM1637 LED controller chip on Arduino platforms. The code was initially part of the AceSegment libra

Feb 2, 2022
Arduino Arduino library for the CloudStorage server project. The library provides easy access to server-stored values and operations.

Arduino-CloudStorage Arduino/ESP8266 library that allows you to easly store and retreive data from a remote (cloud) storage in a key/value fashion. Cl

Jan 30, 2022
CAN / CANFD Arduino Library for Teensy 4.0

CAN Library for Teensy 4.0 / 4.1 It handles Controller Area Network (CAN) for CAN1, CAN2 and CAN3, and Controller Area Network with Flexible Data (CAN

Dec 9, 2022
Arduino library for making an IHC in or output module using an Arduino

Introduction This is an Arduino library for making an IHC in or output module using an Arduino. (IHC controller is a home automation controller made b

Mar 26, 2020
ArduinoIoTCloud library is the central element of the firmware enabling certain Arduino boards to connect to the Arduino IoT Cloud

ArduinoIoTCloud What? The ArduinoIoTCloud library is the central element of the firmware enabling certain Arduino boards to connect to the Arduino IoT

Dec 16, 2022
Leonardo Modifier Keys Controller
Leonardo Modifier Keys Controller

Leonardo Modifier Keys Controller An Arduino Leonardo powered box that allows you to press the modifier keys of the computer. Description An USB devic

May 23, 2022
ESP8266 MQTT Sharp-fu-y30 air purifier controller
ESP8266 MQTT Sharp-fu-y30 air purifier controller

ESP8266 MQTT Sharp-fu-y30 air purifier controller Disclaimer Note: if you decide to do those changes to your air purifier, you take all the responsibi

Dec 6, 2022