problem with communication can bus - problema con la comunicazione can bus

Hi everyone,

I do not speak English very well, so I helped with google translator :sweat_smile:

I have two Arduino DUE with SN65HVD230 transceiver and this is a problem: when I send a value read from pin A0 with the first arduino board to the second arduino board, everything is ok, but when I send the second value read from pin A0 with the first arduino board to the second arduino board the value read remains the previous one.

this is the sent sketch:

#include "Arduino.h"
#include "variant.h"
#include "due_can.h"

#define ID 0x07
#define CAN_MSG_DUMMY_DATA 0x55AAEE22

// CAN frame max data length
#define MAX_CAN_FRAME_DATA_LEN   8

int val = 0;

CAN_FRAME output;

void setup()
{
  Serial.begin(115200);
  Can0.begin(CAN_BPS_125K);
}
void loop(){
  int val = analogRead(A0);
  Serial.print("value ");
  Serial.println(val);
    
  output.id = ID;
  output.length = MAX_CAN_FRAME_DATA_LEN;  
  output.data.low = val;
  output.data.high = CAN_MSG_DUMMY_DATA;
  Can0.sendFrame(output);

  Serial.println("message sent"); 
  delay(2000);
}

this is receive sketch:

#include "Arduino.h"
#include "variant.h"
#include "due_can.h"

#define id 0x07

CAN_FRAME in;

void setup() {
  Serial.begin(115200);
  Can0.begin(CAN_BPS_125K);
  Can0.watchFor(id);
}

void loop() {
  Serial.println("waiting...");
  if(Can0.available()){ 
    Can0.read(in);
    Serial.println("The value received is ");
    Serial.println(in.data.low);
    Serial.println("from ");
    Serial.println(in.data.high, HEX);
    delay(1000);
  }
}

i use due_can library

I am attaching an image

Thanks for the helping

Now in italian

Ciao a tutti

Posseggo due Arduino DUE con due SN65HVD230 per la comunicazione CAN e ho questo problema: quando invio un valore letto dal pin A0 dalla prima scheda Arduino alla seconda scheda Arduino, la comunicazione del valore letto avviene correttamente, ma quando viene letto il secondo valore, sempre dalla prima scheda alla seconda, il valore ricevuto resta il primo. Esempio se il primo valore letto è 800 e questo valore viene trasmesso correttamente, il secondo valore letto ipotizziamo sia 600 il valore ricevuto resta 800, e così anche con la terza, quarta, quinta lettura resterà 800. L' unica soluzione è resettare entrambe le schede e non solo una, ma proprio tutte due.

Gli sketch che ho utilizzato sono sopra
la libreria usata è la due_can
vi lascio un immagine allegata

Grazie mille per l aiuto

I would declare CAN_FRAME output; and CAN_FRAME in; inside loop() rather than outside.

ard_newbie:
I would declare CAN_FRAME output; and CAN_FRAME in; inside loop() rather than outside.

nothing, the problem remains

From SN65HVD23x 3.3-V CAN Bus Transceiver datasheet page 26:

The ISO11898 standard specifies the interconnect to be a single twisted pair cable (shielded or unshielded) with 120 Ω characteristic impedance (ZO).Resistors equal to the characteristic impedance of the line should be used to terminate both ends of the cable to prevent signal reflections.

Did you attach 120 Ohms résistors at each end of CAN bus ?

ard_newbie:
From SN65HVD23x 3.3-V CAN Bus Transceiver datasheet page 26:

The ISO11898 standard specifies the interconnect to be a single twisted pair cable (shielded or unshielded) with 120 Ω characteristic impedance (ZO).Resistors equal to the characteristic impedance of the line should be used to terminate both ends of the cable to prevent signal reflections.

Did you attach 120 Ohms résistors at each end of CAN bus ?

now I put the resistance, but it doesn't change anything

Post a schematic of your wiring.

i took a picture

Your wiring seems OK ( I assume you are using CANRX0 and CANTX0 on both boards).

Since I don't see any issue with the code (maybe someone else could confirm), I suggest that you check your 2 transceivers by uploading the example sketch which comes with the DUE CAN Library called CANExtendedPingPong.ino.

Wire CANRX0/CANTX0 with CANRX1/CANTX1 thru the 2 transceivers and see what happens with CANExtendedPingPong.ino on a single board.

A slightly modified sketch from CANExtendedPingPong.ino and reading A0 (tested, it works on a single board):

#include "variant.h"
#include <due_can.h>

#define TEST1_CAN_TRANSFER_ID    0x11AE756A //random 29 bits
#define TEST1_CAN0_TX_PRIO       15
#define CAN_MSG_DUMMY_DATA       0x11BFFA4E

// CAN frame max data length
#define MAX_CAN_FRAME_DATA_LEN   8

uint32_t sentFrames, receivedFrames;

//Leave this defined if you use the native port or comment it out if you use the programming port
//#define Serial SerialUSB

CAN_FRAME frame1, frame2, incoming;

void setup() {

  Serial.begin(250000);
  
  // Verify CAN0 and CAN1 initialization, baudrate is 1Mb/s:
  if (Can0.begin(CAN_BPS_1000K) &&
	  Can1.begin(CAN_BPS_1000K)) {
  }
  else {
    Serial.println("CAN initialization (sync) ERROR");
  }
  
  //Initialize the definitions for the frames we'll be sending.
  //This can be done here because the frame never changes
  frame1.id = TEST1_CAN_TRANSFER_ID;
  frame1.length = MAX_CAN_FRAME_DATA_LEN;
  //Below we set the 8 data bytes in 32 bit (4 byte) chunks
  //Bytes can be set individually with frame1.data.bytes[which] = something
  frame1.data.low = 0x20103040;
  frame1.data.high = CAN_MSG_DUMMY_DATA;
  //We are using extended frames so mark that here. Otherwise it will just use
  //the first 11 bits of the ID set
  frame1.extended = 1;
  
  frame2.id = TEST1_CAN_TRANSFER_ID + 0x200;
  frame2.length = MAX_CAN_FRAME_DATA_LEN;
  frame2.data.low = 0xB8C8A8E8;
  frame2.data.high = 0x01020304;
  frame2.extended = 1;
  
  //Both of these lines create a filter on the corresponding CAN device that allows
  //just the one ID we're interested in to get through.
  //The syntax is (mailbox #, ID, mask, extended)
  //You can also leave off the mailbox number: (ID, mask, extended)
  Can1.watchFor(TEST1_CAN_TRANSFER_ID + 0x200);
  Can0.watchFor(TEST1_CAN_TRANSFER_ID);
  
  //test_1();
}

// Test rapid fire ping/pong of extended frames
/*static */void test_1(void)
{
  
  CAN_FRAME inFrame;
  uint32_t counter = 0;
        
  // Send out the first frame
  Can0.sendFrame(frame2);
  sentFrames++;

  while (1) {
    delay(1000);
    if (Can0.available() > 0) {
      Can0.read(incoming);
      Serial.print(" Received by CAN0 = ");Serial.println(incoming.data.low);Serial.println(" ");
      frame2.data.low = analogRead(A0);
      Serial.print(" Sent by CAN0 = ");Serial.println(frame2.data.low);
      Can0.sendFrame(frame2);
      delayMicroseconds(100);
      sentFrames++;
      receivedFrames++;
      counter++;
    }
    if (Can1.available() > 0) {
      Can1.read(incoming);
      Serial.print(" Received by CAN1 = ");Serial.println(incoming.data.low);Serial.println(" ");
      frame1.data.low = analogRead(A0);
      Serial.print(" Sent by CAN1 = ");Serial.println(frame1.data.low);
      Can1.sendFrame(frame1);
      delayMicroseconds(100);
      sentFrames++;
      receivedFrames++;
      counter++;
    }
  }
}

// can_example application entry point
void loop()
{
  test_1();
}

ard_newbie:
Your wiring seems OK ( I assume you are using CANRX0 and CANTX0 on both boards).

Since I don't see any issue with the code (maybe someone else could confirm), I suggest that you check your 2 transceivers by uploading the example sketch which comes with the DUE CAN Library called CANExtendedPingPong.ino.

Wire CANRX0/CANTX0 with CANRX1/CANTX1 thru the 2 transceivers and see what happens with CANExtendedPingPong.ino on a single board.

A slightly modified sketch from CANExtendedPingPong.ino and reading A0 (tested, it works on a single board):

#include "variant.h"

#include <due_can.h>

#define TEST1_CAN_TRANSFER_ID    0x11AE756A //random 29 bits
#define TEST1_CAN0_TX_PRIO      15
#define CAN_MSG_DUMMY_DATA      0x11BFFA4E

// CAN frame max data length
#define MAX_CAN_FRAME_DATA_LEN  8

uint32_t sentFrames, receivedFrames;

//Leave this defined if you use the native port or comment it out if you use the programming port
//#define Serial SerialUSB

CAN_FRAME frame1, frame2, incoming;

void setup() {

Serial.begin(250000);
 
  // Verify CAN0 and CAN1 initialization, baudrate is 1Mb/s:
  if (Can0.begin(CAN_BPS_1000K) &&
  Can1.begin(CAN_BPS_1000K)) {
  }
  else {
    Serial.println("CAN initialization (sync) ERROR");
  }
 
  //Initialize the definitions for the frames we'll be sending.
  //This can be done here because the frame never changes
  frame1.id = TEST1_CAN_TRANSFER_ID;
  frame1.length = MAX_CAN_FRAME_DATA_LEN;
  //Below we set the 8 data bytes in 32 bit (4 byte) chunks
  //Bytes can be set individually with frame1.data.bytes[which] = something
  frame1.data.low = 0x20103040;
  frame1.data.high = CAN_MSG_DUMMY_DATA;
  //We are using extended frames so mark that here. Otherwise it will just use
  //the first 11 bits of the ID set
  frame1.extended = 1;
 
  frame2.id = TEST1_CAN_TRANSFER_ID + 0x200;
  frame2.length = MAX_CAN_FRAME_DATA_LEN;
  frame2.data.low = 0xB8C8A8E8;
  frame2.data.high = 0x01020304;
  frame2.extended = 1;
 
  //Both of these lines create a filter on the corresponding CAN device that allows
  //just the one ID we're interested in to get through.
  //The syntax is (mailbox #, ID, mask, extended)
  //You can also leave off the mailbox number: (ID, mask, extended)
  Can1.watchFor(TEST1_CAN_TRANSFER_ID + 0x200);
  Can0.watchFor(TEST1_CAN_TRANSFER_ID);
 
  //test_1();
}

// Test rapid fire ping/pong of extended frames
/*static */void test_1(void)
{
 
  CAN_FRAME inFrame;
  uint32_t counter = 0;
       
  // Send out the first frame
  Can0.sendFrame(frame2);
  sentFrames++;

while (1) {
    delay(1000);
    if (Can0.available() > 0) {
      Can0.read(incoming);
      Serial.print(" Received by CAN0 = ");Serial.println(incoming.data.low);Serial.println(" ");
      frame2.data.low = analogRead(A0);
      Serial.print(" Sent by CAN0 = ");Serial.println(frame2.data.low);
      Can0.sendFrame(frame2);
      delayMicroseconds(100);
      sentFrames++;
      receivedFrames++;
      counter++;
    }
    if (Can1.available() > 0) {
      Can1.read(incoming);
      Serial.print(" Received by CAN1 = ");Serial.println(incoming.data.low);Serial.println(" ");
      frame1.data.low = analogRead(A0);
      Serial.print(" Sent by CAN1 = ");Serial.println(frame1.data.low);
      Can1.sendFrame(frame1);
      delayMicroseconds(100);
      sentFrames++;
      receivedFrames++;
      counter++;
    }
  }
}

// can_example application entry point
void loop()
{
  test_1();
}

Hi,
I'm sorry for keeping you waiting...
I tried with the sketch CANExtendedPingPong and with your sketch, but the results on the serial monitor are "Initialize buffers
Initialize buffers"
stop

So are the broken transceivers?

If the modified sketch I provided in reply #7 do not work for you, you have certainly an hardware issue.

Nevertheless, you can test your CAN BUS software and the board itself without transceivers, here is how you can do that:

See SIEMENS Application Note APNOTE 2921 (On-Board Communication via CAN without Transceiver)

Since the DUE is 3.3V compliant, use a 2.2K Ohms resistor ( or greater) connected to 3.3V (instead of 5V) and use a signal diode similar to 1N914 or 1N4148 ( I tested with a 1.5 meter wire, it works nicely. Some have tested this successfully up to 4 meters).

I'll try tomorrow, but now i have two mcp2515. How can i use this chip on Due?

Tripla-M:
I'll try tomorrow, but now i have two mcp2515. How can i use this chip on Due?

There are a number of MCP2515 libraries that work on the Due. I also maintain one such version you could use:

But, if you don't like that one there are many other choices.

AdderD:
There are a number of MCP2515 libraries that work on the Due. I also maintain one such version you could use:

GitHub - collin80/mcp2515: Library to facilitate CAN functionality with the onboard MCP2515 CAN controller

But, if you don't like that one there are many other choices.

hi

thanks for the help

i bought two new transceiver and now it's work perfectly