I have jumpers on both the MCP2515 boards to enable the 120 Ω termination resistor.
I have probed the can bus and I am able to transmit a message, however the receiver side cannot receive a message. I checked the return value of getStatus() and checkRecieve() and both return 0. The getStatus() method also returns 0 for the tx side but it is transmitting correctly.
I'm unsure as to what the issue could be here and any advice is greatly appreciated.
how have you connected the MCP2515 to the ESP32s?
some sample code I have - it is worth checking if the MCP2515 is initialized OK
// ESP32 CAN Receive Example - note added INPUT_PULLUP to CAN0_INT
//
// ESP32 connections
// MCP2515 INT to ESP32 GPIO22
// MCP2515 SCK to ESP32 GPIO18 CLK
// MCP2515 SI to ESP32 GPIO23 MOSI
// MCP2515 SO to ESP32 GPIO19 MISO
// MCP2515 CS to ESP32 GPIO5 CS
// MCP2515 GND to ESP32 GND
// MCP2515 VCC to ESP32 3.3V
#include <mcp_can.h>
#include <SPI.h>
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128]; // Array to store serial string
#define CAN0_INT 22 // for ESP32
MCP_CAN CAN0(5); //
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("\n\nESP32 CAN MCP2515 shield Send/Receive test - MCP2515 Initialize");
// Initialize MCP2515 baudrate of 250kb/s and the masks and filters disabled.
// check crystal frequency!! e.g. Canbus shield is 16MHz MCP2515 is 8MHz
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
Serial.println("CAN Receive - MCP2515 Initialized Successfully!");
else
Serial.println("Error Initializing MCP2515...");
CAN0.setMode(MCP_NORMAL); // Set operation mode to normal so the MCP2515 sends acks to received data.
pinMode(CAN0_INT, INPUT_PULLUP); // Configuring pin for /INT input *** added PULLUP ***
Serial.println("MCP2515 Library CAN Send/Receive Example\n enter space to send a frame");
}
void loop() {
// check for data received
if (!digitalRead(CAN0_INT)) // If CAN0_INT pin is low, read receive buffer
{
CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s)
if ((rxId & 0x80000000) == 0x80000000) // Determine if ID is standard (11 bits) or extended (29 bits)
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) { // Determine if message is a remote request frame.
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.print((char *)&rxBuf+1);
}
Serial.println();
}
// transmit data when space entered on keyboard
if (Serial.available()) {
if (Serial.read() != ' ') return;
static byte data[8] = { 0x00, 'E', 'S', 'P', '3', '2', 0, 0x08 };
for (byte i = 0; i < 8; i++) {
sprintf(msgString, " 0x%.2X", data[i]);
Serial.print(msgString);
}
// send data: ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
byte sndStat = CAN0.sendMsgBuf(0x100, 0, 8, data);
if (sndStat == CAN_OK) {
Serial.println(" Message Sent Successfully!");
} else {
Serial.println(" Error Sending Message...");
}
data[0]++; // increment first byte of data
}
}
serial monitor output
ESP32 CAN MCP2515 shield Send/Receive test - MCP2515 Initialize
Entering Configuration Mode Successful!
Setting Baudrate Successful!
CAN Receive - MCP2515 Initialized Successfully!
MCP2515 Library CAN Send/Receive Example
enter space to send a frame
0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Error Sending Message...
0x01 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Message Sent Successfully!
0x02 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Message Sent Successfully!
0x03 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Message Sent Successfully!
0x04 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Message Sent Successfully!
0x05 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Message Sent Successfully!
0x06 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Message Sent Successfully!
Standard ID: 0x066 DLC: 8 Data: 0x44 0x44 0x44 0x99 0x99 0xAA 0xAA 0x00
Standard ID: 0x066 DLC: 8 Data: 0x44 0x44 0x44 0x99 0x99 0xAA 0xAA 0x00
Standard ID: 0x066 DLC: 8 Data: 0x44 0x44 0x44 0x99 0x99 0xAA 0xAA 0x00
Unfortunately I only found out that I didn't need the full mcp2515 board after all all the parts arrived. I would ideally like to make the project work with the hardware I have.
how do you know the transmitter works?
it is a good idea when working on Canbus to have a USB-CAN module so you can use a PC to monitor the bus traffic
You have some nice pictures but they do not tell me a lot as I do not have that processor. Posting an annotated schematic showing all connections, power, ground, etc would be a big help.
I don't understand how you've reached this conclusion. It seems you may not fully understand the CAN protocol and its requirements. Please review the information below: In the CAN protocol, an In-Frame Response (IFR) is required from another module on the bus. In other words, for a message to be successfully transmitted, another module must acknowledge the transmission.
I have no idea how you are determining it is not transmitting but you are probably correct. Your bus must be terminated on each end. It is a 60 Ohm bus where termination is 120 Ohms on each end. Also it is a differential bus so there is no real reference to ground, it is dependent on the difference between CAN_H and CAN_L.
Setting Up Arduinos with CAN using MCP2515 Modules
I suggest starting with a few Arduinos and setting them up for CAN communication using MCP2515 CAN modules and Cory Fowler's library: MCP_CAN_lib on GitHub. The send and receive examples work great, and you can combine them to send and receive within a single Arduino UNO. Note that the modules cannot acknowledge themselves; CAN communication requires at least two nodes for acknowledgment.
Important Tips for Setting Up Your CAN Bus:
Connect Grounds: Ensure that the ground from each Arduino UNO is connected to reduce noise. It should work without when working properly.
Bus Termination: Properly terminate both physical ends of the CAN bus with 120 Ohm resistors. Failing to terminate both ends will cause communication issues. You can measure the resistance across the CAN leads using an ohmmeter; a resistance close to 60 Ohms indicates proper termination. Only two terminators are needed in total—none are required for nodes in the middle of the bus.
Crystal Configuration: MCP2515 modules may have different crystals; be sure to set the initialization code to match the specific crystal frequency of your module. Check the module’s specifications for guidance.
CAN Specification: The CAN protocol has two parts:
Part A (CAN 2.0A): Standard format with an 11-bit identifier.
Part B (CAN 2.0B): Extended format with a 29-bit identifier.Most devices will likely use CAN 2.0A. The MCP2515 module connects via SPI and is compatible with other SPI devices, but it’s best to start with just the CAN module first.
Minimum Two Nodes Required: A CAN bus needs at least two active nodes because the protocol requires an acknowledgment within each frame. The receiver must be active during transmission to provide this acknowledgment. If the message isn’t acknowledged, the transmitter will register an error and increment its internal error counter. Once the error count reaches its limit, the transmitter shuts down, a process managed by the CAN controller transparently.
I disagree. What’s actually needed here is a complete bus interface. The MCP2515 module includes a CAN controller but lacks a built-in bus transceiver. The MCP2515 chip handles CAN protocol communication, but it still requires an external transceiver chip to connect to the CAN bus.
For example, you can pair the MCP2515 with a bus transceiver like the TJA1050, which is often the 8-pin component seen on MCP2515 modules. Here’s an image showing a transceiver board with the MCP2515 and CAN bus interface chip:
![MCP2515 Module Image]
In the following schematic, a red line indicates the path through the CAN bus interface chip, showing how these components work together:
![Schematic Image]
Hopefully, this clears things up. Some setups may choose not to use an external bus interface if the transceiver is integrated into another part of the circuit, which seemed to be the case based on the part numbers you mentioned.
the Espressif Two-Wire Automotive Interface (TWAI) on the ESP32 microcontrollers has similar functionality to the MCP2515 and only requires an external transceiver such as the cjmcu-1051 to connect to a canbus network
photo
hi there, i was new..
i try your code using esp32 devkitv1 and got error when sending message.
i do alot tutorial and many of change pin before did i fry my mcp2515.
I use 2 esp32 and 2 mcp2515 which have same error.
ESP32 CAN MCP2515 shield Send/Receive test - MCP2515 Initialize
Entering Configuration Mode Successful!
Setting Baudrate Successful!
CAN Receive - MCP2515 Initialized Successfully!
MCP2515 Library CAN Send/Receive Example
enter space to send a frame
0x00 0x45 0x53 0x50 0x33 0x32 0x00 0x08 Error Sending Message...
looks as though the MCP2515 devices have initialized OK so your SPI connection is OK
how have you connected the two MCP2515 devices together? how far apart? have your the 120ohm terminating resistors? any other devices connected? are the two ESP32 grounds connected?
check the two MCP2515 crystals are the same
I connected with just 2 wire 20cm, with 8mhz crystal.
Both mcp2515 i connected Low to low, and high to high..
I dont connect the ground but both of my esp32 is connected via microusb to same pc.
I also dont use 120ohm, i dont understand where i should put that resistor.. And some tutorials say doesnt need it
updated, i change alot CS PIN, if i dont connect CS PIN message will sent successfully that mean CS PIN is working but MCP2515 sending error during sent message.
i solve the problem, it required pure 5volt
the j1 jumper need be shorted, is already build in 120ohm, no need for adding resistor..
thank to random old man in youtube