How to understand the Waveform of CAN message sent out by Arduino with MCP2515 module

Hi All,
Here is picture for the Waveform of CAN message sent out by Arduino nano+MCP2515 model(with TJA1050).

I do not understand why the first data byte is decode as 0x00? isn't there two bits with "1" in the waveform?
Could you help to give me some instruction. thanks.

below is the code modified from this library
MCP_CAN_lib/examples/CAN_send at master · coryjfowler/MCP_CAN_lib · GitHub

// CAN Send Example
//

#include <mcp_can.h>
#include <SPI.h>

MCP_CAN CAN0(9);     // Set CS to pin D9

void setup()
{
  Serial.begin(115200);

  // Initialize MCP2515 running at 8MHz with a baudrate of 500kb/s and the masks and filters disabled.
  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);   // Change to normal mode to allow messages to be transmitted
}

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

void loop()
{
  // 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...");
  }
  delay(1000);   // send data per 100ms
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

It appears you have very noisy signals, is there a loose connection and is the bus terminated properly? There are bit positions and the level in that time slot is what you should get. Also there is more sent then just your data. Do you have a second unit on the bus that acknowledges the message?

1 Like

Hi gilshultz,
Thanks,I don't have another module to receive the message, it is just sending the message continuously by one module.
and yes, it seems really a noisy signal. is no acknowledge device the cause of the noise? And I'm not sure how to terminated bus properly. The connection seems ok. I Try to hook the CAN_H before and after the 120R ,but there seems not too much difference.

I am sorry to say that will not work, it will keep erroring out and stop trying to send anything. CAN by by definition and hardware design (the CAN chip) requires the acknowledgement, without a second module it will not work. Also by design a module cannot acknowledge itself. Take a look at Corey Fowler's CAN library, it comes with a simple send and receive code ready to compile and load. It worked the first time for me. I have worked with CAN so I knew enough to terminate the bus but I didn't think about the crystal, and I happened to get two with the same value but the code was initialized for a faster one. No problem it worked ok, just a bit slower. I have seen three different crystals on those modules, just look at the init lines.

1 Like

Hi gilshultz,
Thanks, I will buy another MCP2515 module and have a try. the module with a 8MHz crystal.

There is a setting "sample point" in the scope, how will it affect the waveform? I try to updade it from 5% to 95%, it seems nothing change.

And go back to the question, the first data byte seems include 9 bits(edit: 10 bits). and there have two Recessive bits, why it is decode as 0x00h. also same with the send data byte, and the following data...
but 4bits DLC 0x08h seems same with what I was expected.

A proper CAN bus termination is 60 ohms (120 Ohm each end) they must be present at the two physical end points of the CAN network, none inbetween . The CAN network has to be connected from one node to the other with a bus termination for each of the two end points. You can do a search for CAN termination and you will find a lot of data. I really cannot comment on the signal as I do not know your environment or scope. I do know that CAN is a differential signal and your scope ground may inject noise. I have a isolated differential probe for my Tektronix scope and it works just great. You will also need a second Arduino for the second CAN module. This is what mine look like.
image

Hi Gilshultz,
Thanks. I have got another module to receive the CAN message, but the ACK missing issue is still exist. May be there is something wrong with the code.(which I got from CHATGPT :joy:)

Send

#include <SPI.h>
#include <mcp_can.h>

#define CAN0_CS_PIN 10

MCP_CAN CAN(CAN0_CS_PIN); // Set CS pin for MCP2515 module

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) {
    Serial.println("MCP2515 Initialized Successfully!");
    CAN.setMode(MCP_NORMAL);
  } else {
    Serial.println("MCP2515 Initialization Failed!");
  }
}

void loop() {
  unsigned char data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
  CAN.sendMsgBuf(0x100, 0, 8, data);
  delay(1000);
}

Receive

#include <SPI.h>
#include <mcp_can.h>

#define CAN0_CS_PIN 10

MCP_CAN CAN(CAN0_CS_PIN); // Set CS pin for MCP2515 module

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) {
    Serial.println("MCP2515 Initialized Successfully!");
    CAN.setMode(MCP_NORMAL);
  } else {
    Serial.println("MCP2515 Initialization Failed!");
  }
}

void loop() {
  unsigned long rxId;
  unsigned char len = 0;
  unsigned char rxBuf[8];

  if (CAN.checkReceive() == CAN_MSGAVAIL) {
    CAN.readMsgBuf(&rxId, &len, rxBuf);
    Serial.print("Received CAN message with ID: ");
    Serial.print(rxId, HEX);
    Serial.print(", Data: ");
    for (int i = 0; i < len; i++) {
      Serial.print(rxBuf[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}

And I understand the two bits should be ignored when decoding the waveform. They are reverse bits to fill in the waveform after every 5 bits with the same level. And I check the diagram of the module, I didn't short J1 to bring the resistor into the circuit. Just shorted it and Now I'm using the differential type for the scope. it seems much more stable now.
R-C

Now I have to study why I'm still got the ACK error.

Is the jumper installed on J1 on both ends, if not it should be. The bus should be a few feet long. Slow the baud way down, that makes it easier to follow with the scope and makes timing a lot more tolerant. Once you get it going then notch it up.

When a CAN node detects an error in a transmitted message, it transmits an error flag which consists of six bits of the same polarity. The bit stuffing mechanism prevents six consecutive bits from having the same polarity by inserting a bit of opposite polarity after the fifth bit . Try sending 0xAA or 0X55 patterns and see if that helps. You may be encountering the bit stuffing, built into the hardware, this will place an extra bit in the data.

Hi gilshultz,
It seems I didn't update the pin configuration correctly.
It should be **CAN0_CS_PIN 9** instead of **CAN0_CS_PIN 10** for the receiver, now it works and have the ack bit correctly.
The send and receive code of Corey Fowler's CAN library just working fine.

1 Like

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