Help communicating two arduinos with CAN bus

Hello, i want to send CAN data from one arduino to another but i cant, im a “begginer” in arduino, the last (and first) thing i did in arduino was to move a servo with a proximity sensor.

Im using two Keyestudio UNO R3 and Keyestudio Can Bus Shield, so far i was able to read cars, trucks, etc but when i try to make the arduinos “talk” to each other i cannot. Just in case, i do put the arduinos in the same can speed, and i connect them directly with CAN H and CAN L, also tried the DB9, and when i find more info about this they set the MHZ of the shield and i cant see that on mine.

To read the data im using a slightly modified example from the library arduino-mcp2515-master and its this one:

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);


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

  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS);
  mcp2515.setNormalMode();

  Serial.println("------- CAN Read ----------");
  Serial.println("ID  DLC   DATA");
}

void loop() {
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    Serial.print(canMsg.can_id, HEX); // print ID
    Serial.print(" ");
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print(" ");

    for (int i = 0; i < canMsg.can_dlc; i++)  { //
      if (canMsg.data[i] < 0x10) {             //
        Serial.print('0');                       //
      }                                        //
      Serial.print(canMsg.data[i], HEX);
      Serial.print(" ");
    }

    Serial.println();
  }
}

As i said it works fine but im uploading it in case it could be its fault, so moving next to the sender arduino i have tried many different libraries and they didn’t work, also tried using a usb - db9 to send the data and i got another error ( i was using python to do it but it said that’s a readonly bus, same with python → arduino).
For the different libraries i’ve used are: the ones from corey, mc neil, seeduino and some other examples made in base of those (i’ve also used more libraries but don’t know the name of the authors).

What happens when i send the data?, well the arduino seems to send the data ok but the receptor doesn’t display anything on the serial and i think i may need to change a bit of the sender code but dont know where to start. here i’ll put a code that i used and didnt “work”.

#include <CAN.h>
#include <SPI.h> // required to resolve #define conflicts

// Define our CAN speed (bitrate).
#define bitrate CAN_BPS_500K

// data counter just to show a dynamic change in data messages
uint32_t extended_counter = 0;
uint32_t standard_counter = 0;

void setup()
{
  Serial.begin(115200); // Initialize Serial communications with computer to use serial monitor

  //Set CAN speed. Note: Speed is now 500kbit/s so adjust your CAN monitor

  CAN.begin(bitrate);

  delay(4000); // Delay added just so we can have time to open up Serial Monitor and CAN bus monitor. It can be removed later...

  // Output will be formatted as a CSV file, for capture and analysis
  Serial.println(F("millis(),standard_counter,extended_counter"));
}


// Create a function to load and send an extended frame message
void extendedMessage()
{
  CAN_Frame extended_message; // Create message object to use CAN message structure

  // There are at least two ways to put data into the message; memcpy() and individual arrays
  uint8_t message_data[8] = { 0 };

  extended_message.id = 0x02DACBF1; // Random Extended Message ID
  extended_message.valid = true;
  extended_message.rtr = 0;
  extended_message.extended = CAN_EXTENDED_FRAME;
  extended_message.length = 8; // Data length

  // counter in the first 4 bytes, timing in the last 4 bytes
  uint32_t timehack = millis();

  // Load the data into a local array and then use memcpy() to transfer to CAN_Frame
  message_data[0] = (extended_counter >> 24);
  message_data[1] = (extended_counter >> 16);
  message_data[2] = (extended_counter >> 8);
  message_data[3] = (extended_counter & 0xF);
  message_data[4] = (timehack >> 24);
  message_data[5] = (timehack >> 16);
  message_data[6] = (timehack >> 8);
  message_data[7] = (timehack & 0xF);
  memcpy(extended_message.data, message_data, sizeof(extended_message.data));

  CAN.write(extended_message); // Load message and send
  extended_counter++; // increase count
}


// Create a function to load and send a standard frame message
void standardMessage()
{
  CAN_Frame standard_message; // Create message object to use CAN message structure

  standard_message.id = 0x555; // Random Standard Message ID
  standard_message.valid = true;
  standard_message.rtr = 0;
  standard_message.extended = CAN_STANDARD_FRAME;
  standard_message.length = 8; // Data length

  // counter in the first 4 bytes, timing in the last 4 bytes
  uint32_t timehack = millis();

  // Load the data directly into CAN_Frame
  standard_message.data[0] = (standard_counter >> 24);
  standard_message.data[1] = (standard_counter >> 16);
  standard_message.data[2] = (standard_counter >> 8);
  standard_message.data[3] = (standard_counter & 0xF);
  standard_message.data[4] = (timehack >> 24);
  standard_message.data[5] = (timehack >> 16);
  standard_message.data[6] = (timehack >> 8);
  standard_message.data[7] = (timehack & 0xF);

  CAN.write(standard_message); // Load message and send
  standard_counter++; // increase count
}


// Finally arduino loop to execute above functions with a 250ms delay
void loop()
{
  standardMessage();
  delay(250);
  extendedMessage();
  delay(250);
  Serial.print(millis());
  Serial.print(',');
  Serial.print(standard_counter);
  Serial.print(',');
  Serial.println(extended_counter); // adds a line
}

Welcome to the forum

First we should check your hardware setup. It sounds like so far you only connected to existing CAN bus systems. Can you please provide a link to the CAN bus shield datasheet you are using?

For CAN you need to have termination resistors (120 Ohm) on both ends of the bus. Can you confirm you have them on the shield and they are connected. Some boards have on board termination and use a jumper to connect/disconnect them, because you should only have one on each end and not on each node. If you modules do not have termination resistors you need to connect some externally.

I actually dont have it with jumpers or anything to show an image of it, but to read i put the wire directly in CAN H and CAN L and then to the OBD2/ DB9 or the port that i needed to read, and to connect the arduinos i did the same, a wire directly between the CAN pins. How that worked for reading i just repeated

CAN BUS SHIELD : https://wiki.keyestudio.com/images/5/57/0411-图片1.png
UNO R3: https://i1.wp.com/varpertechnologies.com/wp-content/uploads/2020/01/1_H467a5abddc5146f5aba7a26e46e3e215o.png?fit=1000%2C1000&ssl=1

Edit: whenever i get the second arduino back i'll try adding those resistors and update the thread with what happened

I found the following page and it confirms, there are no termination resistors on board. And they added two pads for a SMD version.

https://wiki.keyestudio.com/KS0411_keyestudio_CAN-BUS_Shield

Your sender code doesn't define the 'chip select' pin or set the operating mode.
The default chip select pin defined in the library may not work for your hardware.

Generally speaking when using a library you test it using the provided 'sender' and 'receiver' example as they are made to work together. Your code looks like it was written for two different libraries.

Hello so rn im doing test and here is what happends but first, thanks to both for helping me

So, i added a 121 ohm resistor in one of the arduinos and now i can send messages!! so really thanks to @Klaus_K for helping me with that.

Now i can send and recieve messages normally but, something that seems quite interesting is that i noticed when i read with my arduino an id for example "0x14FEF100" it reads it as "0x94FEF100" and also for ids starting with 0 it changes it for a 8, don't know exactly why is that and im going to do some more testing to guess how that works, also i have to say that if the id starts with 8 or 9 it doesn't get any change, if anyone has any clue about that it would be really much appreciated! if not both helped me a lot THANKS

edit: the change of the leading numbers i got it before and after adding the resistor

sharho:
Now i can send and recieve messages normally but, something that seems quite interesting is that i noticed when i read with my arduino an id for example "0x14FEF100" it reads it as "0x94FEF100" and also for ids starting with 0 it changes it for a 8, don't know exactly why ...

Can you please provide information about the CAN library. e.g. a link to the Github page or how it is installed?

0x94FEF100 is not a valid CAN ID, it is a 32bit number (Extended IDs are 29-bit). Maybe there is an issue how the ID is copied.

this is the library i use: GitHub - autowp/arduino-mcp2515: Arduino MCP2515 CAN interface library
i try to send that id because i got it as speed from reading a Mercedes Benz New Actros, the one i got from using PCANVIEW was 14FEF100 and it was 94FEF100 in my arduino readings, the problem with this id's is that they dont get recognized from my MDVR

It looks like the library uses the first three bits of the ID to store some flags. Have a look at the following file.

/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000UL /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000UL /* remote transmission request */
#define CAN_ERR_FLAG 0x20000000UL /* error message frame */

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