Go Down

Topic: Building a CAN API for Arduino DUE (Read 139 times) previous topic - next topic

Collin80

Oops, I did miss that bug in your code. The data line should be:

myFrame.data.bytes[0] = 0xFF;

The data member of the structure is a union full of different types of access patterns so you can access it by byte, by 16 bit int, by 32 bit int, or by 64 bits all at once.

gambit1244

thank you Collin,
i compile and run this code and im watching the arduino's can ports via my logic analyzer.
after the reset i can see the initalize logic levels, after init, tx ports high , rx ports staying low positions and nothing more :(
i didnt connect my transceiver chips yet. logic analyzer directly connected to can tx -rx pins directly
why i cant see the id and data
when i connect my logic analyzer to my can bus data logger's ports i can see the all id and data but arduino doesnt work :(


i think you might be busy but i need really help collin :( thank you again
warm regards

Collin80

To help narrow it down you should try two things:

1. Compile and run one of the example sketches that sends data. The pingpong sketch should be fine for this. It should immediately saturate the bus with attempts to deliver frames.
2. You don't happen to have another Due do you? (I'm doctor Suess now)

Manewc

Hi

Thanks a million for this thread makes everything much easier, i have a question which is of the options below is viable with due arduino and which one would be best with an arduino ethernet shield.

http://www.ti.com/product/sn65hvd233

http://www.wvshare.com/product/SN65HVD230-CAN-Board.htm

http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010405

Thanks for your help this will help me with my project

manewc

Collin80

Manewc,

The first two use the SN65HVD23X transceiver (where X is 0,3,4, etc). That transceiver will work fine. I really wouldn't recommend using the MCP2551 as it assumes a 5V tolerant MCU which the Due is not. If you are building a one-off prototype then the second link with a breakout board would probably be ideal. But, if you're going to use another board like an ethernet shield, then you might be able to add the bare SN65HVD chip on a prototyping section. All the ethernet shields I found don't have such an area though.

zabaat

My thanks again to Collin and Palliser!

I've built a number of these boards for a project but placed my clamping diode incorrectly and will have to run them again. They are perfectly fine for someone that won't be going over the 36V input range ever.  I think they would be quite nice for someone who is looking to tinker and wants a stable platform to do so.

It has placements for a 9-36V input, a pheonix contact push in connector for powre and CAN, a multi dip switch and all the caps. I've used it with the arduino due and the DigiX due clone with great success. Also dual ethernet.

I've soldered it all by hand so you shouldn't need to be too scared of it.

If someone is interested let me know. dimensions are 4.4" square.


TT_ZX

Many thanks to Collin, Palliser and everyone else that has contributed to this library.  I am working on a project that will have up to 22 nodes on a single bus.  Without this library I don't think I could attempt this with my limited knowledge.

I have a couple of questions that hopefully someone could comment on.

1. I want to isolate each node on the bus.  This is because the bus length will be up to 100m and each node will have it's own power supply (230VAC at each node).  So far my testing has been using the SN65HVD234 transceivers and they work very well.  But to isolate each node I'm thinking that I'd need to either us some optocouplers between the transceiver and micro controller or change to a different transceiver.  I quick Google turns up the ISO1050 which is available locally.  Here's the datasheet:
http://www.ti.com/lit/ds/symlink/iso1050.pdf
Am I on the right track?  Has anyone else done something similar?

2. Can the due_can library be used with the AT90CAN series of micro controllers?

Collin80


1. I want to isolate each node on the bus.  This is because the bus length will be up to 100m and each node will have it's own power supply (230VAC at each node).  So far my testing has been using the SN65HVD234 transceivers and they work very well.  But to isolate each node I'm thinking that I'd need to either us some optocouplers between the transceiver and micro controller or change to a different transceiver.  I quick Google turns up the ISO1050 which is available locally.  Here's the datasheet:
http://www.ti.com/lit/ds/symlink/iso1050.pdf
Am I on the right track?  Has anyone else done something similar?


Good thinking. The ISO1050 works fine with the Due and with the due_can library. I do have experience with this. The GEVCU project has several (> 50) boards out in the field with that exact transceiver. We haven't blown up the transceiver or board yet.

Quote

2. Can the due_can library be used with the AT90CAN series of micro controllers?


No. The AT90CAN series of processors are 8 bit AVR processors and this library is meant specifically for the 32 bit ARM Cortex M3 processor in the Due.

g4rb4g3

#428
Sep 07, 2014, 06:49 pm Last Edit: Sep 07, 2014, 07:15 pm by g4rb4g3 Reason: 1
Hi there,

I'm trying to get an Arduino Due to work with my car but init functions always returns 0 when the transcreceiver is connected to the cars bus system.
I'm using a transcreceiver board with the SN65HVD230 chip (http://www.wvshare.com/product/SN65HVD230-CAN-Board.htm). As far as I understood this thread it should work with the library here.

I guess the main problem is that the cars bus is working at 100Kbit/s while this library doesn't seem to support it.
At least in the due_can.h there are only higher or lower values, so I added a line for 100Kbit/s.
Code: [Select]
#define CAN_BPS_100K                  100000
I found out that the CANRaw::set_baudrate functions seems to work out and it does return 1. But I'm not realy sure if the can_bit_time array has the right values for the desired speed.
I understand some of the code but as a java and .net programmer c(++) code is pretty hard to understand for me (especialy the bit-shifting ... :smiley-eek:).

So maybe someone here could help me out and tell me if the code should work with 100Kbit/s or if it needs some modification. If it does it would be great to get some hints for the right direction  :).

Edit: I forgot to mention that I removed the 120 Ohm resistor on the board already since this is not the start/end point of the bus.

Collin80

Yes, all of that should work fine. There is an array for bit timing but it isn't directly tied to the actual canbus speed. In theory you should be able to set any canbus speed. But, some speeds will not be possible to exactly reach. I'd imagine that 100k baud wouldn't be a problem. But, if you try to set it to 46,247 baud you'll probably have trouble.

that_kid

I can confirm that it does work fine at 100k, I tested this in my car on the infotainment bus which runs at that speed.

g4rb4g3


I can confirm that it does work fine at 100k, I tested this in my car on the infotainment bus which runs at that speed.


Could you please provide me some more infos about your setup?
I'm trying to get access to the K-Can on a BMW E91, maybe your experience could help me a bit.

that_kid

I added a #define for 100k as you did and was able to connect to the 100k infotainment and comfort bus in my VW Touareg.  I'm grabbing the can bus lines from the radio/nav socket in the dash.  I also was able to connect from the bus lines connected to the digital amp in the back.  I didn't need a terminating resistor on the Arduino side either.

agrawalk

#433
Sep 23, 2014, 07:42 pm Last Edit: Sep 23, 2014, 07:45 pm by agrawalk Reason: 1
Hey Guys,

so I need some help. I am trying to implement a CAN Bus interface using the arduino due. I am using your library 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.


###Here is the ino code ###



// 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

g4rb4g3


Yes, all of that should work fine. There is an array for bit timing but it isn't directly tied to the actual canbus speed. In theory you should be able to set any canbus speed. But, some speeds will not be possible to exactly reach. I'd imagine that 100k baud wouldn't be a problem. But, if you try to set it to 46,247 baud you'll probably have trouble.


Thank you, I've tried it again today and now it works. :smiley-eek:
I'm not sure why, I know for sure that I didn't change anything on the software side and that I didn't change anyhting on the cables between the Arduino and the transreceiver board. Maybe I just connected the can bus the wrong way around last time... I guess so.
I just added a comment to my sketch so I know how to connect it the right way now for sure. ;)

Go Up