Testing CAN/SPI communication on the ESP32 PLC 14

How to set up and test CAN bus communication between two ESP32 PLC 14 units using the CAN SPI click module and Arduino IDE
June 12, 2026 by
Testing CAN/SPI communication on the ESP32 PLC 14
Boot & Work Corp. S.L, Queralt del Águila Munté

In this blog post, we explain how to test CAN bus communication between two ESP32 PLC 14 units using the CAN SPI 5V click module and Arduino IDE.

Hardware setup: connecting the CAN SPI click

The ESP32 PLC 14 has one additional communication slot compatible with the CAN SPI click. Connect the H and L pins between the two units. A two-wire connection works, but a 3-point CAN bus cable is recommended for better signal integrity.

Software setup: libraries and pin definitions

Install the industrialshields-esp32 board on the Arduino IDE: go to Tools > Board > Boards Manager and search for "industrialshields-esp32". Then select Tools > Board > Industrial Shields ESP32 > 14 IOS PLC Family.

Download and install the MCP_CAN library: Sketch > Include Library > Add .ZIP Library. The library is available at github.com/coryjfowler/MCP_CAN_lib.

Create a defs.h file inside a new folder in your Arduino Libraries folder, paste the following definitions, and restart the Arduino IDE.

#include "MCP23017.h"

#define In0 11
#define In1 10
#define In2 12
#define In3 13
#define In4 4
#define In5 6
#define In6 5
#define S0_24v 15
#define S1_24v 14
#define S2_24v 1
#define S3_24v 0
#define Relay 7
#define PWM_click 9
#define INT_click 8

#define INTA 13   // Expander interrupt
#define Out0 32
#define Out1 25
#define Out2 26
#define Out3 27
#define CS0 14    // Ethernet
#define CS1 4     // Click
#define A0420 32  // Analog 4..20mA
#define A1420 33
#define A0010 34  // Analog 0..10v
#define A1010 35

#define pwrPin 2
#define resetPin 3
#define INT_click 8
#define PWM_click 9
#define INTA 13   // Expander interrupt
#define CS0 14    // Ethernet
#define CS1 4     // Click

#define UART1 0x78
#define Bit0 0x00

// MCP I2C CONFIG
const uint8_t sda = 21;
const uint8_t scl = 22;
uint8_t mcp_i2c_address = 0x20;
MCP23017 mcp(mcp_i2c_address);

CAN send sketch

Upload the following sketch to the sender ESP32 PLC 14:

#include "defs.h"
#include "Wire.h"
#include <mcp_can.h>

MCP_CAN CAN0(CS1);

byte data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

void setup() {
  Serial.begin(115200UL);
  delay(1000);

  pinMode(CS1, OUTPUT);
  delay(100);
  digitalWrite(CS1, LOW);
  delay(1000);

  if (!mcp.begin(sda, scl)) {
    Serial.print(-1);
    while (1);
  }
  delay(1000);

  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 initialized successfully!");
  else
    Serial.println("Error initializing MCP2515...");

  CAN0.setMode(MCP_NORMAL);
}

void loop() {
  uint8_t sndStat = CAN0.sendMsgBuf(0x111, 0, 8, data);

  if (sndStat == CAN_OK) {
    Serial.println("Message sent successfully!");
  } else {
    Serial.println("Error sending message...");
  }
  delay(3000);
}

CAN receive sketch

Upload the following sketch to the receiver ESP32 PLC 14:

#include "defs.h"
#include "Wire.h"
#include <mcp_can.h>

MCP_CAN CAN0(CS1);

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];

void setup() {
  Serial.begin(115200UL);
  delay(1000);

  pinMode(CS1, OUTPUT);
  delay(100);
  digitalWrite(CS1, LOW);
  delay(1000);

  if (!mcp.begin(sda, scl)) {
    Serial.print(-1);
    while (1);
  }
  delay(1000);

  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 initialized successfully!");
  else
    Serial.println("Error initializing MCP2515...");

  CAN0.setMode(MCP_NORMAL);
}

void loop() {
  CAN0.readMsgBuf(&rxId, &len, rxBuf);

  if ((rxId & 0x80000000) == 0x80000000)
    sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxId & 0x1FFFFFFF), len);
  else
    sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);

  Serial.print(msgString);

  if ((rxId & 0x40000000) == 0x40000000) {
    sprintf(msgString, " REMOTE REQUEST FRAME");
    Serial.print(msgString);
  } else {
    for (byte i = 0; i < len; i++) {
      sprintf(msgString, " 0x%.2X", rxBuf[i]);
      Serial.print(msgString);
    }
  }
  Serial.println();
  delay(500);
}

Once both sketches are running on separate ESP32 PLC 14 units, open the Serial Monitor on the receiver to confirm that CAN messages are arriving correctly.

​Search in our Blog

Testing CAN/SPI communication on the ESP32 PLC 14
Boot & Work Corp. S.L, Queralt del Águila Munté June 12, 2026
Share this post
Tags

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

PLC Comparison