Please Help Arduino CANsendMsg and CANrecieveMsg not working with multiple CAN nodes

Hi I am a newer user to Arduino and I have been trying to utilize some seeed studio CAN-BUS V2 shields to send and receive data over. I have been running into an issue where when I send the data from my Arduino Uno to my Arduino Mega which works fine, but when I try to send the same data back from Mega to the other Mega it stops receiving data from the Uno correctly and doesn't even send the message.
Can I not send and receive messages from the same Arduino device and or is there something im missing?

This is the current set up with wires connecting the CAN H and CAN L ports of each device to one another while the code for each device is as follows
UNO

#include <SPI.h>          //SPI is used to talk to the CAN Controller
#include <mcp_can.h>
#include <Encoder.h>
Encoder myEnc(2, 3);    // connect encoder on digital Pin 2 and 3

MCP_CAN CAN(9);          //set SPI Chip Select to pin 10

int encoderPin1 = 2;
int encoderPin2 = 3;
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
volatile long lastencoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;
byte data[4] = {225,3,0,0};
byte data_NMT[2] = {1,1};
long newPosition;

void setup()
{
  Serial.begin(115200);   //to communicate with Serial monitor
  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);
  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
  attachInterrupt(digitalPinToInterrupt(2), updateEncoder, CHANGE); //interrupts the pin based on a change noticed in the pin and calls a function
  attachInterrupt(digitalPinToInterrupt(3), updateEncoder, CHANGE);
START_INIT:

    if(CAN_OK == CAN.begin(CAN_1000KBPS))      //setting CAN baud rate to 1000Kbps but actually its going to be 500KBPS because CAN module has 8MHz crystal not 16MHz
    {
        Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println("Init CAN BUS Shield again");
        delay(100);
        goto START_INIT;
    }
}

//loading the data bytes of the message. Up to 8 bytes

void loop()
{   
  newPosition = encoderValue*.1066;
  Serial.println(newPosition);
  CAN.sendMsgBuf(27, 0, 1 ,(byte *) &newPosition );
  delay(100);
}

void updateEncoder()
{
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //combining it with the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; //clockwise
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; //counter clockwise

  lastEncoded = encoded; //store this value for next time 
}

MEGA Recieve and Sender

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

MCP_CAN CAN(9);          //set SPI Chip Select to pin 10

unsigned char len = 0;
unsigned char buf[8];
unsigned int canID;
int angle;
int Newangle;
int pos;
int Newpos;
int current;
int Newcurrent;

void setup()
{
  Serial.begin(115200);   //to communicate with Serial monitor
START_INIT:

    if(CAN_OK == CAN.begin(CAN_1000KBPS))      //setting CAN baud rate to 1000Kbps but actually its going to be 500KBPS because CAN module has 8MHz crystal not 16MHz
    {
        Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println("Init CAN BUS Shield again");
        delay(100);
        goto START_INIT;
    }
}



void loop()
{
    if(CAN_MSGAVAIL == CAN.checkReceive())    //check if data is coming
    {
        CAN.readMsgBuf(&len, buf);
        canID = CAN.getCanId();
        //Serial.println(canID);
        if(canID == 27)
        {
          //Serial.println(buf[0]);
          angle = buf[0]*1.406;
          Serial.println(angle);
          Newangle = angle*.1066;
          CAN.sendMsgBuf(30, 0, 1 ,(byte *) &Newangle );  
        }
        if(canID == 28)
        {
          pos = buf[0];
          Serial.println(pos);
          Newpos = pos;
          CAN.sendMsgBuf(31, 0, 1 ,(byte *) &Newpos );
        }
        if(canID == 29)
        {
          current = buf[0];
          Serial.println(current);
          Newcurrent = current;
          CAN.sendMsgBuf(32, 0, 1 ,(byte *) &Newcurrent );
        }
        
        
        //CAN.readMsgBuf(&len, buf);    //read data,  len: data length, buf: data buffe
        
        //Serial.println(buf[0]*1.406);     //Serial.write prints the character itsel
      
    }
}

MEGA Reciever

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

MCP_CAN CAN(9);          //set SPI Chip Select to pin 10

unsigned char len = 0;
unsigned char buf[8];
unsigned int canID;
int angle;
int Newangle;
int pos;
int Newpos;
int current;
int Newcurrent;

void setup()
{
  Serial.begin(115200);   //to communicate with Serial monitor
START_INIT:

    if(CAN_OK == CAN.begin(CAN_1000KBPS))      //setting CAN baud rate to 1000Kbps but actually its going to be 500KBPS because CAN module has 8MHz crystal not 16MHz
    {
        Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println("Init CAN BUS Shield again");
        delay(100);
        goto START_INIT;
    }
}



void loop()
{
    if(CAN_MSGAVAIL == CAN.checkReceive())    //check if data is coming
    {
        CAN.readMsgBuf(&len, buf);
        canID = CAN.getCanId();
        if(canID == 30)
        {
          angle = buf[0]*1.406;
          Serial.println(angle);
        }
        if(canID == 31)
        {
          pos = buf[0];
          Serial.println(pos);
        }
        if(canID == 32)
        {
          current = buf[0];
          Serial.println(current);
        }
        
        
        
        //CAN.readMsgBuf(&len, buf);    //read data,  len: data length, buf: data buffe
        
        //Serial.println(buf[0]*1.406);     //Serial.write prints the character itself
      
    }
}

Here I am attempting to send a message from Uno to Mega receive and sender, where the Mega receive and sender then sends it to the Mega receiver

When I have the Sendmsg. commented out in the Mega receiver and sender Code everything runs fine, but when I try to run it with the send message uncommented it no longer works

Your frizzy picture is not much help. I see no power, termination or transceiver information. . How about a complete schematic with links to technical information on the hardware devices.

Encoder http://domoticx.com/sensor-lpd3806-optical-rotary-encoder/
Mega https://docs.arduino.cc/hardware/mega-2560
CAN-BUS Shield https://www.seeedstudio.com/CAN-BUS-Shield-V2.html
Uno https://docs.arduino.cc/hardware/uno-rev3

Each device is plugged in to my computer from their usb b port while running, covering the power source

In terms of transcievers and termination my wiring set up looks exactly like the image above minus the usb cables connecting back to my laptop

I also edited in a less fuzzy picture

Here is the original though:

Sounds good but the picture is not readable on my machine. You must have a magic shield, when I use the MCP2515 I have to define the crystal frequency. Why start at max baud, that is the most critical speed to run it at and debug it. I see no indication of termination are the jumpers in place on the end modules? I use the same library and currently I have about 7 modules connected and operating properly at 250K.

I am sorry about that, I hope viewing the link will help as there is not as much pixel loss, but I have a seeed studio can-bus shield v2
That would be awesome to get to work, I've been trying for a month or so now and have been hitting my head against a wall trying to get this to work. To answer your questions I can lower the baud rate, what setting would you recommend?
In terms of termination I am not sure what you mean, I have edited the source in the link to include numbers next to the wires, as i'm not sure what you are referring to

You have spent a lot of time but in the process learned a lot. I would suggest watching some tutorials on CAN systems with the Arduino etc. A lot of them will be about connecting to the OBD system. Download this from TI: https://www.ti.com/lit/pdf/SLLA270 That will give you a lot of information but it is not an easy or quick read. They show what termination is, how to put it on your system, etc. Here is another link that will help: https://www.kvaser.com/lesson/can-physical-layers/ If you look at the send and receive code in the library it will show how to set the crystal frequency in your code. You can get that number by looking at the top of the crystal in your shield. When a CAN message is sent part of the actual message is an acknowledgement from another member on the bus, if it does not get it it cycles a counter, when it counts out an error flag is set and it quits transmitting. Good Luck.

Just briefly after looking at some of your documents I updated the wiring diagram to better fit what I think it is supposed to look like to add termination to the circuit

It also seems like the documentation is indicating that if a module is transmitting, another module will wait until it has finished the transmission before sending, so if im having an issue sending the message from the Mega it is because the Uno is still sending data. If I have a delay after sending the data shouldn't the Mega have enough time to then send its own message? I also assume I must ground each device to one another to prevent interrupting currents

You have the gist of the arbitration but it works on a dominance and recessive modes of the bus. Anybody can come on the bus when they want. They need to check if it is quiet, then starts. It monitors each bit on the buss and if it is in error it turns itself off and tries again later. This lets the message with the higher priority bet through. The spec does not require grounding but it helps keep the common mode offsets out of the loop. Here is the line I use to initialize my MCP2515s. I have a 8 Mhz crystal and running at 250KBPS. Set mode to normal.
if(CAN0.begin(MCP_ANY,CAN_250KBPS , MCP_8MHZ) == CAN_OK) Also Set mode to normal. CAN0.setMode(MCP_NORMAL);

Thank you for that, earlier you said you were using the same library as me, but an issue I get when I try to run your start up to initialize my Cans it says MCP_ANY was not initialized in this scope, do I have to initialize this before hand or should this already be a preset in the library?

I found a different library than the one I am using that uses the same syntax as you have, before I was using a seeed studio Can library

I connected the modules up via SPI, loaded the software examples from the library, connected the CAN A to A and B to B buses from each together added the terminating jumpers. I loaded the software, started the transmitter then the receiver and it worked. I did change the config line in the sample to match my crystal and baud I wanted. I then took eich piece of code, made a function out of it and then called them sequentially performing other functions in the code as well. Start with the can and use the pins defined in the library, I believe it does use interrupts.

Just for the sake of clarity I am now using GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library
is this the library you are using?

NEW UPDATE:
Uno code

// CAN Send Example
//

#include <mcp_can.h>
#include <SPI.h>
#include <Encoder.h>
Encoder myEnc(2, 3);

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

int encoderPin1 = 2;
int encoderPin2 = 3;
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
volatile long lastencoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;
long newPosition;

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

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
  else Serial.println("Error Initializing MCP2515...");

  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);
  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
  attachInterrupt(digitalPinToInterrupt(2), updateEncoder, CHANGE); //interrupts the pin based on a change noticed in the pin and calls a function
  attachInterrupt(digitalPinToInterrupt(3), updateEncoder, CHANGE);

  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted
}

void loop()
{
  // send data:  ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
  newPosition = encoderValue*.1066;
  Serial.println(newPosition);
  byte sndStat = CAN0.sendMsgBuf(27, 0, 1 ,(byte *) &newPosition );
  if(sndStat == CAN_OK){
    Serial.println("Message Sent Successfully!");
  } else {
    Serial.println("Error Sending Message...");
  }
  delay(100);   // send data per 100ms
}

void updateEncoder()
{
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //combining it with the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; //clockwise
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; //counter clockwise

  lastEncoded = encoded; //store this value for next time 
}

Mega send and receive code

// CAN Receive Example
//

#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

int angle;
int Newangle;
int pos;
int Newpos;
int current;
int Newcurrent;

#define CAN0_INT 2                              // Set INT to pin 2
MCP_CAN CAN0(10);                               // Set CS to pin 10


void setup()
{
  Serial.begin(115200);
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("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);                            // Configuring pin for /INT input
  
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
  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)
    Serial.println(rxId);
    Serial.println(rxBuf[0]);
    Newpos = rxBuf[0];
    delay(50);
    if (rxId==27)
    {
    byte sndStat = CAN0.sendMsgBuf(30, 0, 1 ,(byte *) &Newpos );
    if(sndStat == CAN_OK){
    Serial.println("Message Sent Successfully!");
    } else {
      Serial.println("Error Sending Message...");
    }
    }
    

    Serial.println();
  }
}

Mega receive code

// CAN Receive Example
//

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

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];  
int angle;
int Newangle;
int pos;
int Newpos;
int current;
int Newcurrent;// Array to store serial string

#define CAN0_INT 2                              // Set INT to pin 2
MCP_CAN CAN0(9);                               // Set CS to pin 10


void setup()
{
  Serial.begin(115200);
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("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);                            // Configuring pin for /INT input
  
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
  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)
    Serial.println(rxId);
    Serial.println(rxBuf[0]);
    Newpos = rxBuf[0];
    Serial.println();
    
        
    Serial.println();
  }
}

This code is now working.....ish, I seem to be sending and receiving messages at the same time, now the issue is when I attempt to do this there is still an issue of outputting a message of zero, and no messages come up as unable to send, or that there has been an issue sending. The message of zero seems to be due to the fact that once trying to send and receive from the mega the encoder values continue to collect as 0

Once I remove the send part of the message the encoder begins to read the values fine, I figured I would also send an image of the set up, It is as described in the wiring schematic.

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