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 Teensy 3.x ACAN library https://github.com/pierremolinaro/acan, ACAN2515 library https://github.com/pierremolinaro/acan2515, and the ACAN2517FD library https://github.com/pierremolinaro/acan2517, it uses a very similar API and the same CANMessage class for handling messages.

ACAN2517 library description

ACAN2517 is a driver for the MCP2517FD CAN Controller, in CAN 2.0B mode. It runs on any Arduino compatible board.

The ACAN2517FD library handles the MCP2517FD CAN Controller, in CAN FD mode.

The library supports the 4MHz, 20 MHz and 40 MHz oscillator clock.

The driver supports many bit rates: 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/LoopBackDemo 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 MCP2517_CS  = 20 ; // CS input of MCP2517FD, adapt to your design
static const byte MCP2517_INT = 37 ; // INT output of MCP2517FD, adapt to your design

ACAN2517FD can (MCP2517_CS, SPI, MCP2517_INT) ; // You can use SPI2, SPI3, if provided by your microcontroller

void setup () {
  Serial.begin (9600) ;
  while (!Serial) {}
  Serial.println ("Hello") ;
  ACAN2517Settings settings (ACAN2517Settings::OSC_4MHz10xPLL, 125 * 1000) ; // 125 kbit/s
  settings.mRequestedMode = ACAN2517RequestedMode::InternalLoopBackMode ; // Select loopback mode
  const uint32_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 unsigned gSendDate = 0 ;
static unsigned gSentCount = 0 ;
static unsigned 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 MCP2517 CAN Controller implements 32 acceptance masks and 32 acceptance filters. The driver API enables you to fully manage these registers.

For example (LoopBackDemoTeensy3xWithFilters sketch):

  ACAN2517Settings settings (ACAN2517Settings::OSC_4MHz10xPLL, 125 * 1000) ;
  settings.mRequestedMode = ACAN2517 RequestedMode::LoopBackMode ; // Select loopback mode
  MCP2517Filters filters ;
// Filter #0: receive standard frame with identifier 0x123
  filters.appendFrameFilter (kStandard, 0x123, receiveFromFilter0) ;
// Filter #1: receive extended frame with identifier 0x12345678
  filters.appendFrameFilter (kExtended, 0x12345678, receiveFromFilter1) ; 
// Filter #2: receive standard frame with identifier 0x3n4
  filters.appendFilter (kStandard, 0x70F, 0x304, receiveFromFilter2) ;
  const uint32_t errorCode = can.begin (settings, [] { can.isr () ; }, filters) ;

These settings enable the acceptance of standard frames whose identifier is 0x123, extended frames whose identifier is 0x12345678, and data frames whose identifier is 0x304, 0x314, ..., 0x3E4, 0x3F4.

The receiveFromFilter0, receiveFromFilter1, receiveFromFilter2 functions are call back functions, handled by the can.dispatchReceivedMessage function:

void loop () {
  can.dispatchReceivedMessage () ; // Do not use can.receive any more
  ...
}
Comments
  • ESP32 compatibility

    ESP32 compatibility

    Hi Pierre- Great job with these new ACAN2515 and ACAN2517 drivers! Most other MCP2515/2517 drivers seem to be lacking in various areas, but your ACAN drivers look excellent and very easy to use. Im looking forward to experimenting with them.

    One question I had was regarding Espressif ESP32 compatibility. The Arduino ESP32 SPI drivers are a bit different in that they do not support the spi.usingInterrupt function. When I compile the ACAN2515/2517 test programs for ESP32, the compiler gives an error because the "usingInterrupt" does not exist in ESP32.

    Just as a quick experiment, I modified your source files (ACAN2515.cpp/ACAN2517.cpp) and commented out line 156 "mSPI.usingInterrupt (itPin)".

    On my work bench here with an MCP2517 development board (MCP2517 with a 20Mhz Ceralock resonator), with that mSPI.usingInterrupt line removed, the ACAN2517 driver initializes "ok", and it does send out CAN messages correctly. It does NOT receive any messages correctly though.

    My tests were done with low speed single-wire CAN (33.333k) used on some GM/Opel/Saab vehicles, with a TH8056 single-wire-CAN transceiver connected to the MCP2517.

    I could not make it send or receive with traditional 500k CAN. Perhaps something wrong with oscillator settings or my use of a 20MHz resonator and not a true 40MHz crystal?

    I assume the receiving problem was due to the ACAN driver not correctly using the interrupt trigger from the MCP2517 due to the fact that I removed the usingInterrupt function.

    Do you have any ideas on how to modify the driver to work correctly with the ESP32's SPI hardware?

    Thanks Ben

  • MCP2518FD with Arduino Mega

    MCP2518FD with Arduino Mega

    Hello I am using the MCP2518FD Click Board with an Arduino Mega but the MCP2518FD cant be accessed via SPI (Error0x1). I know there exist already Issues with the same Error , but it didnt really help me.

    I am using the following wiring: MOSI(51) --> SDI MISO(50) --> SDO CS(53) --> CS SCK(52) --> SCK INT(2) --> INT 5V --> 5V 3.3V --> 3.3V I am using the loopback code with the configuration as shown as in the Picture. I hope somebodey can help me with this. Thank you and best regarts. Unbenannt

  • Sample Code In Description

    Sample Code In Description

    Shouldn't the sample code, ACAN2517FD can (MCP2517_CS, SPI, MCP2517_INT); instead instantiate the class: ACAN2517 can (MCP2517_CS, SPI, MCP2517_INT);

    This library seems to be for Classic can (non-FD), but using the Microchip 2517FD device? Also compiling the sample code generates the error: "ACAN2517RequestedMode' has not been declared"

    The above might be just an issue on my end, I'm trying to port the code to a non-arduino processor. Perhaps I should try converting to C?

  • TRANSMIT_FIFO_INDEX is 0 (should be 2)

    TRANSMIT_FIFO_INDEX is 0 (should be 2)

    I haven't been able to build your Arduino code as I don't have a suitable shield for an Arduino, but I am using it as a starting point for code to run on a Pi PICO with a MCP2518 attached. Looking at the code I se TRANSMIT_FIFO_INDEX is defined as 0, but functions like C1FIFOCON_REGISTER() expect 1..31 (according to the comments). I think using C1FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) will produce a register address for CiTXQCON (0x50) not CiFIFOCON1 (0x5C). Peter Onion

  • CAN-transmission errors

    CAN-transmission errors

    Hello Pierre, but once again about my problem with the transmission errors, because it may not be (only) because of the SPI transmission rate. For this purpose I examined my "good" circuit, which did not generate any errors, i.e. the one with the 20MHz crystal on the MCP and the SPI transmission with 10MHz generated with it. The peculiarity here is that one message is specifically sent in a time interval

    • Experimental setup 1: ESP32 and MCP2518 with 20MHz crystal, SPI, no interrupt pin, no data is received in the ESP32, it is only sent. I am sending a message with 6 bytes of data at a frequency of 4 KHz. The CAN runs at 1MBaud, resulting in a bus load of approx. 41%. No other participant on the bus sends further data. Everything works fine, over 10 million messages sent, no errors.
    • Experiment setup 2: Exactly the same as 1, the following change: the CAN now runs with 500kBaud. This leads to a bus load of approx. 82%. Now errors occur, remote frames are received and also messages that were never sent. (approx. 1 error per 10000 transmissions) The stress with the higher bus load is only caused by the MCP, the SPI transmission does not change. He only sends alone, so he doesn't have to fight for priorities. I can't explain why ...
    • Experiment setup 3: Exactly the same as 1, the following change: 4 different messages are sent in the program from the ESP to the MCP in direct succession. The transmission frequency for these 4 messages is 1KHz, so the CAN bus load is again at 40%. Now errors arise: Specifically sent: CAN-ID(hex): 320, 321, 322, 323 - 45000 each, received: 320 and 321 each 45000, 322: 44992, 323: 44110, additionally the following messages and number on ID(hex): 302: 8; 303: 890 It is noticeable here that the last 2 messages are badly affected. I have solved the problem by waiting 70µs after each sending of a message before I send the next one. Then it runs without errors. I can't really explain that to myself, because I'm writing in the buffer, but that's how it is.

    But that is just a deceptive "good condition". Because if a second device sends data on the bus and the bus load increases again, to around 60%, then these errors occur again.

    Do you have any idea? So when the MCP gets stressed, errors occur on the bus. Which settings can you adjust? Thanks.

  • My car Nexa has only implemented J1979 so no passive reading of CAN data. How to send and receive response

    My car Nexa has only implemented J1979 so no passive reading of CAN data. How to send and receive response

    Hi My car Nexa has only implemented J1979 so I am not able to read raw CAN data using MCP2515 and also with MCP2517FD but with MCP2515 I am able to send requests to CAN like RPM and able to receive responses.

    My question is using MCP2517 how can I send the request and receive a response like the below code for MCP2515:

    `if (useStandardAddressing) { CAN.beginPacket(0x7df, 8); } else { CAN.beginExtendedPacket(0x18db33f1, 8); } CAN.write(0x02); // number of additional bytes CAN.write(0x01); // show current data CAN.write(0x0c); // engine RPM CAN.endPacket();

    // wait for response while (CAN.parsePacket() == 0 || CAN.read() < 3 || // correct length CAN.read() != 0x41 || // correct mode CAN.read() != 0x0c); // correct PID

    float rpm = ((CAN.read() * 256.0) + CAN.read()) / 4.0;

    Serial.print("Engine RPM = "); Serial.println(rpm);`

  • Multiple call to begin cause memory problems

    Multiple call to begin cause memory problems

    Hi,

    Due to low power reasons I'm turning off can device and turn again when necessary. I've found that after calling (code below) for some times, I've get memory problems.

    const uint32_t errorCode = can.begin (settings, isr_can, filters) ;

  • NRF52840 ACAN2518 at Normal20B receiving but not transmitting

    NRF52840 ACAN2518 at Normal20B receiving but not transmitting

    Hi. I'm using NRF52840 and library ACAN2717 version 1.1.10 and I'm facing some problem when trying to transmit frame data. When running on loopback mode is ok, I can send and received frame data, but when running on Normal20B I can receive can data but when I transmit I get no error, but the data is not sent.

    Se my code below:

    ACAN2517Settings settings (ACAN2517Settings::OSC_20MHz, 500 * 1000) ;
    settings.mRequestedMode = ACAN2517Settings::Normal20B;//InternalLoopBack;//
    
    //----------------------------------- Append filters
    ACAN2517Filters filters ;
    filters.appendFrameFilter (kStandard, PID_VIN, receiveVinData);
    filters.appendFrameFilter (kStandard, PID_KC_ODOMETER, receiveOdometerData);
    filters.appendFrameFilter (kStandard, PID_KC_SPEED, receiveSpeedData);
    filters.appendFrameFilter (kStandard, 0x777, receiveGeneric);
    filters.appendFrameFilter (kStandard, 0x778, receiveGeneric);
    filters.appendFrameFilter (kStandard, 0x779, receiveGeneric);
    
    //----------------------------------- Filters ok ?
    if (filters.filterStatus () != ACAN2517Filters::kFiltersOk) {
        debug.println("Error filter:  %d : %d ", filters.filterErrorIndex(), filters.filterStatus());
    }
    //----------------------------------- Enter configuration
    const uint32_t errorCode = can.begin (settings, [] { can.isr_core () ; }, filters) ;
    //----------------------------------- Config ok ?
    if (errorCode == 0)
    {
        debug.println("Bit Rate prescaler: %d", settings.mBitRatePrescaler);
        debug.println("Phase segment 1: %d", settings.mPhaseSegment1);
        debug.println("Phase segment 2: %d", settings.mPhaseSegment2);
        debug.println("SJW: %d", settings.mSJW);
        debug.println("Actual bit rate: %d bit/s", settings.actualBitRate());
    
        debug.println("Exact bit rate ? %s", settings.exactBitRate() ? "yes" : "no");
        debug.println("Sample point: %d%", settings.samplePointFromBitStart());
        debug.println("currentOperationMode: %d", can.currentOperationMode());
    }
    else
    {
        debug.println("Configuration error %x", errorCode);
    }
    

    And now the log information: Configure ACAN2517FD Bit Rate prescaler: 1 Phase segment 1: 31 Phase segment 2: 8 SJW: 8 Actual bit rate: 500000 bit/s Exact bit rate ? yes Sample point: 80 currentOperationMode: 6 Configure ACAN2517FD done

    At send operation I get: Sent OK, with no error

    Do you know if some addition settings is required to work with CAN20B at 500kbps?

MCP2515 CAN Controller Driver for Arduino

MCP2515 CAN Controller Library for Arduino Compatibility with the ACAN library This library is fully compatible with the Teensy 3.x ACAN library https

Dec 13, 2022
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

Dec 18, 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
An implementation of a ANT driver for Arduino, Mbed and ESP-IDF

ant-arduino Arduino library for communicating with ANT radios, with support for nRF51 devices. This library Includes support for the majority of packe

Dec 4, 2022
CAN Driver for Teensy 3.1 / 3.2, 3.5 and 3.6

CAN Library for Teensy 3.1 / 3.2, 3.5, 3.6 Compatibility with the ACANxxxx libraries This library is fully compatible with the MCP2515 CAN Controller

Dec 9, 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
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
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
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
Driver for Texas Instrument's ADS1115 analog to digital converter IC.

Driver for Texas Instrument's ADS1115 analog to digital converter IC. It's somewhat compatible with the ADS1113 and ADS1114 variants. More details in the official datasheet

Sep 27, 2021
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
A RESTful environment for Arduino

aREST Overview A simple library that implements a REST API for Arduino & the ESP8266 WiFi chip. It is designed to be universal and currently supports

Dec 29, 2022
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
Unified interface for selecting hardware or software SPI implementations on Arduino platforms

AceSPI Unified interface for selecting hardware or software SPI implementations on Arduino platforms. The code was initially part of the AceSegment li

Oct 22, 2021