Error using the CAN library with ESP32S2 Dev Module

Hi there, I'm looking for assistance in fixing a set of errors I'm having with the Arduino CAN Library [CAN - Arduino Reference] as I try to use it with the ESP32S2 Dev Module. I've been following this link as a guide for using the CAN library for the ESP32 system [What is CAN Bus & How to use CAN Interface with ESP32 and Arduino - CIRCUITSTATE Electronics].

When I try to compile the code I first received a message stating:


After looking troubleshooting I found this link [System - ESP32 - — ESP-IDF Programming Guide v5.0.6 documentation] recommending changing "esp_intr.h" to "esp_intr_alloc.h".

Once I made this change a new set of errors have appeared, which primarily state that a set of DPORT related variables (apologies if I used the wrong term here, I'm not familiar with this set of registers) is not declared in the scope. Here is a snippet of the errors I am receiving - more errors continue in the same vein as those displayed.


Perhaps a fix for this is adjusting the included files but I'm unfamiliar with the architecture of the board to know where to look and I have not found a solution online.

I've been unable to find a solution to these errors and any assistance in getting to the bottom of them would be amazing. I understand that perhaps this library may not be compatible with the ESP32S2 chip or perhaps I've skipped over some obvious note in the block of red-text-error - so this may have ended up being a dumb question, so thanks again for any help.

Show us all the code using code tags. Also all the error msgs again using code tags.

Thank you for the response. For this project I'm using the ESP32S2 Dev Module from Espressif's esp32 system. The minimal reproducible example of the code is the inclusion statement for the CAN library:

#include <CAN.h>

Which then produces the following error:

In file included from /Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_reg.h:21,
                 from /Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:7:
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp: In member function 'virtual int ESP32SJA1000Class::begin(long int)':
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:56:53: error: 'DPORT_CAN_RST' was not declared in this scope; did you mean 'DPORT_WDG_RST'?
   56 |   DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
      |                                                     ^~~~~~~~~~~~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:78:88: note: in definition of macro '_DPORT_WRITE_PERI_REG'
   78 | #define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)
      |                                                                                        ^~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:88:46: note: in expansion of macro 'DPORT_WRITE_PERI_REG'
   88 | #define DPORT_CLEAR_PERI_REG_MASK(reg, mask) DPORT_WRITE_PERI_REG((reg), (DPORT_READ_PERI_REG(reg)&(~(mask))))
      |                                              ^~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:56:3: note: in expansion of macro 'DPORT_CLEAR_PERI_REG_MASK'
   56 |   DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:57:51: error: 'DPORT_CAN_CLK_EN' was not declared in this scope; did you mean 'DPORT_USB_CLK_EN'?
   57 |   DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
      |                                                   ^~~~~~~~~~~~~~~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:78:88: note: in definition of macro '_DPORT_WRITE_PERI_REG'
   78 | #define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)
      |                                                                                        ^~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:91:46: note: in expansion of macro 'DPORT_WRITE_PERI_REG'
   91 | #define DPORT_SET_PERI_REG_MASK(reg, mask)   DPORT_WRITE_PERI_REG((reg), (DPORT_READ_PERI_REG(reg)|(mask)))
      |                                              ^~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:57:3: note: in expansion of macro 'DPORT_SET_PERI_REG_MASK'
   57 |   DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
      |   ^~~~~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:61:26: error: 'CAN_RX_IDX' was not declared in this scope; did you mean 'TWAI_RX_IDX'?
   61 |   gpio_matrix_in(_rxPin, CAN_RX_IDX, 0);
      |                          ^~~~~~~~~~
      |                          TWAI_RX_IDX
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:61:3: error: 'gpio_matrix_in' was not declared in this scope
   61 |   gpio_matrix_in(_rxPin, CAN_RX_IDX, 0);
      |   ^~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:62:3: error: 'gpio_pad_select_gpio' was not declared in this scope; did you mean 'esp_rom_gpio_pad_select_gpio'?
   62 |   gpio_pad_select_gpio(_rxPin);
      |   ^~~~~~~~~~~~~~~~~~~~
      |   esp_rom_gpio_pad_select_gpio
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:66:27: error: 'CAN_TX_IDX' was not declared in this scope; did you mean 'TWAI_TX_IDX'?
   66 |   gpio_matrix_out(_txPin, CAN_TX_IDX, 0, 0);
      |                           ^~~~~~~~~~
      |                           TWAI_TX_IDX
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:66:3: error: 'gpio_matrix_out' was not declared in this scope; did you mean 'gpio_iomux_out'?
   66 |   gpio_matrix_out(_txPin, CAN_TX_IDX, 0, 0);
      |   ^~~~~~~~~~~~~~~
      |   gpio_iomux_out
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp: In member function 'virtual void ESP32SJA1000Class::end()':
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:171:51: error: 'DPORT_CAN_RST' was not declared in this scope; did you mean 'DPORT_WDG_RST'?
  171 |   DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
      |                                                   ^~~~~~~~~~~~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:78:88: note: in definition of macro '_DPORT_WRITE_PERI_REG'
   78 | #define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)
      |                                                                                        ^~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:91:46: note: in expansion of macro 'DPORT_WRITE_PERI_REG'
   91 | #define DPORT_SET_PERI_REG_MASK(reg, mask)   DPORT_WRITE_PERI_REG((reg), (DPORT_READ_PERI_REG(reg)|(mask)))
      |                                              ^~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:171:3: note: in expansion of macro 'DPORT_SET_PERI_REG_MASK'
  171 |   DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
      |   ^~~~~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:172:53: error: 'DPORT_CAN_CLK_EN' was not declared in this scope; did you mean 'DPORT_USB_CLK_EN'?
  172 |   DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
      |                                                     ^~~~~~~~~~~~~~~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:78:88: note: in definition of macro '_DPORT_WRITE_PERI_REG'
   78 | #define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)
      |                                                                                        ^~~
/Users/scottbrown/Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-dc859c1e67/esp32s2/include/soc/esp32s2/include/soc/dport_access.h:88:46: note: in expansion of macro 'DPORT_WRITE_PERI_REG'
   88 | #define DPORT_CLEAR_PERI_REG_MASK(reg, mask) DPORT_WRITE_PERI_REG((reg), (DPORT_READ_PERI_REG(reg)&(~(mask))))
      |                                              ^~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:172:3: note: in expansion of macro 'DPORT_CLEAR_PERI_REG_MASK'
  172 |   DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp: In member function 'virtual void ESP32SJA1000Class::onReceive(void (*)(int))':
/Users/scottbrown/Documents/Arduino/libraries/CAN/src/ESP32SJA1000.cpp:283:20: error: 'ETS_CAN_INTR_SOURCE' was not declared in this scope
  283 |     esp_intr_alloc(ETS_CAN_INTR_SOURCE, 0, ESP32SJA1000Class::onInterrupt, this, &_intrHandle);
      |                    ^~~~~~~~~~~~~~~~~~~

exit status 1

Compilation error: exit status 1
  • Scott

It looks like you need another library as well.

I just installed the CAN library. I then loaded the sample sketch CanReceiver and it compiled clean for a NANO but failed on missing esp_intr.h. I am stumped for the moment.

I just rolled back the esp32 boards to 2.0.17 and it compiled BUT it has the following warning

 #warning esp_intr.h is deprecated, please include esp_intr_alloc.h instead [-Wcpp]

It looks like the author has not fixed the library code. You can either do the same and roll back, but then you will need to do that any time you were working with CAN unless you blocked ALL updates which I strongly advise against. Try contacting the author on github.

Thank you so much for the help. I've spent some time working on a solution to be able to use the CAN Bus system on the ESP32 without having to rollback the boards. I found a simple way to get CAN to work by using the 'ESP32-TWAI-CAN' library [ESP32-TWAI-CAN - Arduino Reference] which is more bare-bones than the CAN library but this can be supplemented by reading over the TWAI documentation for the ESP32: Two-Wire Automotive Interface (TWAI) - ESP32 - — ESP-IDF Programming Guide v5.3 documentation.

I used this following code to test this library:

#include <ESP32-TWAI-CAN.hpp>

#define CAN_TX   45  // Connects to CTX
#define CAN_RX   46  // Connects to CRX

CanFrame rxFrame; // Create frame to read 

void setup() {
  // Set up serial for debugging
  Serial.begin(115200);
  delay(500);

  // Set the pins
  ESP32Can.setPins(CAN_TX, CAN_RX);
  Serial.println("test3");

  // Start the CAN bus at 500 kbps
  if(ESP32Can.begin(ESP32Can.convertSpeed(500))) {
      Serial.println("CAN bus started!");
  } else {
      Serial.println("CAN bus failed!");
  }
}

void loop() {
  canSender();  // call function to send data through CAN
  //canReceiver(); // call function to recieve data through CAN
}

void canSender() {
  // send packet: id is 11 bits, packet can contain up to 8 bytes of data
  Serial.print("Sending packet ... ");

  CanFrame testFrame = { 0 };
  testFrame.identifier = 0x12;  // Sets the ID
  testFrame.extd = 0; // Set extended frame to false
  testFrame.data_length_code = 8; // Set length of data - change depending on data sent
  testFrame.data[0] = '1'; // Write data to buffer. data is not sent until writeFrame() is called.
  testFrame.data[1] = '2';
  testFrame.data[2] = '3';
  testFrame.data[3] = '4';
  testFrame.data[4] = '5';
  testFrame.data[5] = '6';
  testFrame.data[6] = '7';
  testFrame.data[7] = '8';

  ESP32Can.writeFrame(testFrame); // transmit frame
  Serial.println("done");

  delay(1000);
}

void canReceiver() {
  // try to parse packet
  if(ESP32Can.readFrame(rxFrame, 700)) { // 1000 is the timeout value
    // Communicate that a packet was recieved
    Serial.printf("Received frame: %03X \r\n", rxFrame.identifier);

    // Communicate packet information
    for(int i = 0; i <= rxFrame.data_length_code - 1; i ++) {
      Serial.print((char) rxFrame.data[i]); // Transmit value from the frame 
    }
  } else {
    Serial.println("No frame recieved");
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.