Arduino Due CAN API ?

Hey Guys,

so I need some help. I am trying to implement a CAN Bus interface using the arduino due. I am using the library (found here GitHub - collin80/due_can: Object oriented canbus library for Arduino Due compatible boards) discussed here (http://forum.arduino.cc/index.php/topic,131096.0.html) as a template but was having some issues.

Currently I am trying to send Can messages from by due to my computer ( I have industrial level software that shows me can messages). Specifically the software I am using is called CANalyzer provided by Vector.

I have in various parts of my code instrumented more code to check whether all the register values are being read correctly and are in fact valid. I have include images of the register values( printed via serial port) along with my code so you can cross check.

The issue I am having is although the CANalyzer software detects a message on the line it detects a "error frame". Furthermore if you see then message breakdown (CANaylzer allows you to see the error frame breakdown) you will notice that all relevant values i.e. ID & Data are correct.

Obviously as per Can protocol at 128 messages failed to send ( as the due gets no acknowledgement) the Can timeouts.

Additional info:
I am using (2 * 120 || 120 ) terminating resistors.

Please let me know if you need anything more.

// Required libraries
#include "variant.h"
#include "due_can.h" 

#define TEST1_CAN_TRANSFER_ID   0x1FFFFFFF //11 bits Standard //random 29 bits Extended
#define TEST1_CAN0_TX_PRIO       1
#define CAN_MSG_DUMMY_DATA       0xABC

// 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() {

   // start serial port at 115200 bps: 
   Serial.begin(115200);

   // Serial port intializied
   Serial.print("Serial Port Initialized\n"); 

   // Verify CAN0 and CAN1 initialization, baudrate is 0.25Mb/s:
   if (CAN.init(CAN_BPS_250K) &&
      CAN2.init(CAN_BPS_250K)) {
   }
   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.fid = 0x000000A3;
   frame1.length = MAX_CAN_FRAME_DATA_LEN;
   //Priority
   frame1.priority = 0;
   frame1.rtr = 1;
   //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 = 0xA;
   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;

   //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)
   CAN2.setRXFilter(0, TEST1_CAN_TRANSFER_ID + 0x200, 0x1FFFFFFF, true);
}

// Test rapid fire ping/pong of extended frames
static void test_1(void)
{

   Serial.println("******START OF LOOP ******");
   CAN_FRAME inFrame;
   uint32_t counter = 0;
   // Send out the first frame
   CAN.sendFrame(frame1);
   sentFrames++;
   Serial.print("No of Sent frames: ");
   Serial.println(sentFrames);
   /*
   CAN.printCAN_MR();
   Serial.println("############");
   CAN.printCAN_IER();
   Serial.println("############");
   CAN.printCAN_IDR();
   Serial.println("############");
   CAN.printCAN_IMR();
   Serial.println("############");
   CAN.printCAN_SR();
   Serial.println("############");
   CAN.printCAN_MID7();
   Serial.println("############");
   CAN.printCAN_ECR();
   Serial.println("############");
   CAN.printCAN_ECR();
   delay(5000);
   */
   delay(2000);
   Serial.println("<><><><><><><><><>><><><><>");
   CAN.printCAN_ECR();
   Serial.println("<><><><><><><><><>><><><><>");
   Serial.println("#####END OF LOOP ######");

}


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

Thanks in advance.
Kamil

How to use this forum

Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the # button above the posting area.

As you got the library from github the best thing to do is really to register for a free github account and raise and issue in github with the developer.

rogerClark:
As you got the library from github the best thing to do is really to register for a free github account and raise and issue in github with the developer.

That certainly can be done but I do visit this board too so either way works.

agrawalk:
Hey Guys,

so I need some help. I am trying to implement a CAN Bus interface using the arduino due. I am using the library (found here GitHub - collin80/due_can: Object oriented canbus library for Arduino Due compatible boards) discussed here (http://forum.arduino.cc/index.php/topic,131096.0.html) as a template but was having some issues.

One thing I see is that the ID is set to 29 1's as the ID aka the very maximum possible ID. I'm not sure that you are allowed to do that. I'm nearly positive you shouldn't use an ID of 0 either. Try something in the middle. But, try some other IDs and see if things begin to work better. One thing for sure. If you use 0x1FFFFFFF as the ID and then try to add +200 you will overflow the 29 bits anyway. And, such a line is found in your code.

Lots of people have used the library for lots of things so I'm not leaning toward it actually being in error but maybe. I will do some tests to make sure that there isn't some sort of issue that was found.

Collin I have tried multiple variations,

Also as for the +200 you are talking about that's the filter on Can2(which is can1 in arduino MC terms) correct?

I don't think that would matter in my case because, I am only sending messages and not receiving them. The only place the filter is useful is when you have incoming messages. Furthermore I am only using Can1 (which is Can0 in MC terms so the filter doesn't even apply).

// Required libraries
#include "variant.h"
#include "due_can.h" 

#define TEST1_CAN_TRANSFER_ID   0x18FF0017 //11 bits Standard //random 29 bits Extended
#define TEST1_CAN0_TX_PRIO       1
#define CAN_MSG_DUMMY_DATA       0xABC

// 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() {

	// start serial port at 115200 bps: 
	Serial.begin(115200);

	// Serial port intializied
	Serial.print("Serial Port Initialized\n"); 

	// Verify CAN0 and CAN1 initialization, baudrate is 0.25Mb/s:
	if (CAN.init(CAN_BPS_250K) &&
		CAN2.init(CAN_BPS_250K)) {
	}
	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.fid = 0x000000A3;
	frame1.length = MAX_CAN_FRAME_DATA_LEN;
	//Priority
	frame1.priority = 0;
	frame1.rtr = 1;
	//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 = 0xAFAFAFAF;
	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;

	//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)
	//CAN2.setRXFilter(0, TEST1_CAN_TRANSFER_ID + 0x200, 0x1FFFFFFF, true);
}

// Test rapid fire ping/pong of extended frames
static void test_1(void)
{

	Serial.println("******START OF LOOP ******");
	CAN_FRAME inFrame;
	uint32_t counter = 0;
	// Send out the first frame
	CAN.sendFrame(frame1);
	sentFrames++;
	Serial.print("No of Sent frames: ");
	Serial.println(sentFrames);
	/*
	CAN.printCAN_MR();
	Serial.println("############");
	CAN.printCAN_IER();
	Serial.println("############");
	CAN.printCAN_IDR();
	Serial.println("############");
	CAN.printCAN_IMR();
	Serial.println("############");
	CAN.printCAN_SR();
	Serial.println("############");
	CAN.printCAN_MID7();
	Serial.println("############");
	CAN.printCAN_ECR();
	Serial.println("############");
	CAN.printCAN_ECR();
	Serial.println("############");
	printCAN_MSR7()
	delay(5000);
	*/
	delay(2000);
	Serial.println("<><><><><><><><><>><><><><>");
	CAN.printCAN_BR();
	Serial.println("<><><><><><><><><>><><><><>");
	Serial.println("#####END OF LOOP ######");

}


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

I tried the above code and set a little more detail on my CanAylzer and got the attached result. Seems like I am getting no acknowledgement from the arduino and its a recessive error flag (bit error). On the MC side I am not getting the acknowledgment as well. I have attached the register output aswell.

Hey,
just to update. I've used an oscilloscope to track down the problem. The issue seems to be the an incorrect CRC calculation.

I've attached the results of this. Anyone know a work around as the CRC is something I have no control over and is generated at the hardware level.

Here is the link for the results.
https://drive.google.com/folderview?id=0BwRY4KO_k7sUdmN5RWJVZnFHSVE&usp=sharing

Here is another forum where I posted the same question. It might have some additional details.

Thanks,
Kamil

I have read everything in this thread and the one on stackexchange. I still do not know why the CRC portion seems to be wrong. I have to suspect a hardware issue at this point but even that seems odd because you'd expect a hardware issue to manifest all of the time, not just during the CRC portion. There are a couple of options:

  1. Maybe your Due is subtly damaged. You could try a different one.
  2. Maybe your other end (the dongle for canalyzer) is broken or otherwise acting weird.

That is, try to change both ends, one at a time, to see if the problem goes away. I've used various Due compatible hardware and never seen this problem but I have not used CANAlyzer so maybe there is something odd there. As someone told you in the SE thread, maybe try changing the sampling point in CANAlyzer to see if it helps. Otherwise see if you can dig up a different canbus dongle and see if it works better.

Collin,
I have tried multiple Due's(over 5). The same problem persists. As for the Canaylzer dongle I highly doubt it. Its a $1000+ dongle for industry standard use.

Further evidence of the dongle working fine was found when, I used it to read J1939 Can Messages off of a truck. the messages seemed well formatted and correct.

Can you please include a list of dongles and Software you have used. I know Busmaster was mentioned as "free" analyzing tool.

Ps: did you happen to look at the Google Drive Folder?

Thanks
Kamil

Agrawalk,

Were you ever able to figure out what your issue was? I am having the same issue and I am having a hard time figuring out how to fix this issue.

For me changing the Baud rate to 500k worked.