Categorieën bekijken

ESP32 – CAN FD

In this example we are using a MCP2518 SPI CAN controller and a ISO1042 Isolated CAN transciever (powered by a Isolated DC-DC buck) for CAN 2.0B Classic communication on a ESP32.

Connection schematic:


MCP2517 MCP2518FD Arduino Library #

Source: https://github.com/pierremolinaro/acan2517FD


Example code #

This example code is wirting 64-byte long messages over the canbus in FD mode

Notice this settings line:

ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_20MHz, 250UL * 1000UL, DataBitRateFactor::x1) ;

Here you can set:

  • Oscillator Frequency (20MHz)
  • 250UL (250Kbit/s) (arbitrary bitrate)
  • Databitrate factor x arbitrary bitrate (x1 = same as arbitrary bitrate)

For more info you can always view the github repository.

Note:

The 0x01 error is raised when the MCP2517FD does not reach the configuration mode in 2ms. It means that the MCP2517FD cannot be accessed via SPI, check the hardware connections.

//  ACAN2517FD or ACAN2518FD send-even
#include <ACAN2517FD.h>

// USING ESP32 VSPI pins
// CLK:  GPIO 18
// MISO: GPIO 19
// MOSI: GPIO 23
// CS:   GPIO 5

static const byte MCP2517_CS  = 5 ; // CS pin of MCP2517
static const byte MCP2517_INT = 26 ; // INT pin of MCP2517

ACAN2517FD can (MCP2517_CS, SPI, MCP2517_INT) ;

void setup () {
  Serial.begin (115200) ;
  SPI.begin () ;
  ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_20MHz, 250UL * 1000UL, DataBitRateFactor::x1) ;
  settings.mDriverReceiveFIFOSize = 200 ;
  const uint32_t errorCode = can.begin (settings, [] { can.isr () ; }) ;
  Serial.print ("Bit Rate prescaler: ") ;
  Serial.println (settings.mBitRatePrescaler) ;
  Serial.print ("Arbitration Phase segment 1: ") ;
  Serial.println (settings.mArbitrationPhaseSegment1) ;
  Serial.print ("Arbitration Phase segment 2: ") ;
  Serial.println (settings.mArbitrationPhaseSegment2) ;
  Serial.print ("Arbitration SJW:") ;
  Serial.println (settings.mArbitrationSJW) ;
  Serial.print ("Actual Arbitration Bit Rate: ") ;
  Serial.print (settings.actualArbitrationBitRate ()) ;
  Serial.println (" bit/s") ;
  Serial.print ("Exact Arbitration Bit Rate ? ") ;
  Serial.println (settings.exactArbitrationBitRate () ? "yes" : "no") ;
  Serial.print ("Arbitration Sample point: ") ;
  Serial.print (settings.arbitrationSamplePointFromBitStart ()) ;
  Serial.println ("%") ;
  Serial.print ("Data Phase segment 1: ") ;
  Serial.println (settings.mDataPhaseSegment1) ;
  Serial.print ("Data Phase segment 2: ") ;
  Serial.println (settings.mDataPhaseSegment2) ;
  Serial.print ("Data SJW:") ;
  Serial.println (settings.mDataSJW) ;
  Serial.print ("TDCO:") ;
  Serial.println (settings.mTDCO) ;
  Serial.print ("Even, error code 0x") ;
  Serial.println (errorCode, HEX) ;
  while (errorCode != 0) { } //Endless  loop on error
}

static uint32_t gBlinkLedDate = 0 ;
static uint32_t gSentFrameCount = 0 ;
static uint32_t gReceivedFrameCount = 0 ;
static bool gCompleted = false ;
static const uint32_t SEND_COUNT = 50 * 1000 ;

static void handleReceivedMessages (void) {
  CANFDMessage frame ;
  while (can.receive (frame)) {
    gReceivedFrameCount ++ ;
  }
}

void loop () {
  handleReceivedMessages () ;
  if (gBlinkLedDate < millis ()) {
    gBlinkLedDate += 1000 ;
    digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
    if (!gCompleted) {
      Serial.print ("Sent: ") ;
      Serial.print (gSentFrameCount) ;
      Serial.print (", received: ") ;
      Serial.print (gReceivedFrameCount) ;
      Serial.print (", errors ") ;
      Serial.print (can.errorCounters (), HEX) ;
      Serial.print (", op mode ") ;
      Serial.print (can.currentOperationMode ()) ;
      Serial.print (", rcved buffer ") ;
      Serial.print (can.driverReceiveBufferPeakCount ()) ;
      Serial.print (", overflows ") ;
      Serial.println (can.hardwareReceiveBufferOverflowCount ()) ;
      gCompleted = (gReceivedFrameCount >= SEND_COUNT) && (gSentFrameCount >= SEND_COUNT) ;
    }
  }
  if (gSentFrameCount < SEND_COUNT) {
    CANFDMessage frame ;
    frame.id = micros () & 0x7FE ;
    frame.len = 64 ;
    for (uint8_t i=0 ; i<frame.len ; i++) {
      frame.data [i] = i ;
    }
    const bool ok = can.tryToSend (frame) ;
    if (ok) {
      gSentFrameCount += 1 ;
    }
  }
}

Example output: #

Example output on a Pi system

  can0  63E  [64]  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14
15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
  can0  3A2  [64]  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14
15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
  can0  10E  [64]  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14
15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F