Go Down

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

zabaat

Thank you for the great response! Would it be possible for me to roll through different can ids and data locations as I looped? so in other words I could still have 8 mailboxes per loop but have toggle that redirected the mailboxes after each send? I'll try this tomorrow

Collin80

Yes, you can reconfigure the mailboxes any time you want. You can change what a mailbox does every loop if you want to.

Transistorfips

Hi guys,
here's a quick update of my CAN OBD analyzer:
http://imageshack.us/photo/my-images/707/glhn.jpg/
The software is still under construction, I use a simulator from Ozen Elektronik (a turkish brand) instead of my car. The Display is a Touch-LCD from lcd-module.de.
Speed, rpm, coolant temp and vehicle frame number are readable (multi-frame transfer took me a while to fiddle with).
I only use the DUE hardware, software is a modified can example for the SAM3X-EK board.

DUE rocks!


Owais

Hello, Can anyone please explain the function of mailbox_set_accept_mask(); both in case of transmitter as well as receiver mailbox.

Thanks,

Owais.

Collin80


Hello, Can anyone please explain the function of mailbox_set_accept_mask(); both in case of transmitter as well as receiver mailbox.

Thanks,

Owais.


Sure. For transmission mailboxes it means absolutely nothing. The examples might call that function but it is just for completeness and not because you have to. Transmissions will go out no matter how you have the accept mask set.

Now, such is not the case for receiving mail boxes. That's where the accept mask comes into play. It works like this:

1. A frame is sent over the wire and picked up by the Due.
2. The ID of the frame is logical AND with the accept mask
3. This new value is then compared to the id you set for the RX mailbox (mailbox_set_id). If the IDs match then the frame is accepted and available for your program to inspect.

Here is an example. Let's say you set your accept mask to 0x7F0 and your ID to 0x230 (assume only standard frames). Now, a frame with ID 0x232 comes in. So, take 0x232 AND 0x7F0 = 0x230. Compare this to the mailbox ID you set (0x230) and find out that it matches. So, the frame is accepted by your program. Now, if a frame with ID 0x23A comes in then the same thing will happen. If 0x240 comes in then it will be rejected.

In a nutshell: the accept mask allows you to accept a range of frame IDs with a single mailbox. In the example above it allows a range of 16 IDs through 0x230 - 0x23F. The traditional use for this is to tailor acceptance to only frames you care about. Canbus traffic can get busy and you don't want to have to deal with every frame on the bus.

Owais

Thank you very much Collin80 its crystal now.

Transistorfips

Hi guys,
today I compiled the due_can project the first time with Visual Micro + AS6.1. The second example from Collin brought:

Compiling 'Arduino_Due_CAN_Sample_2' for 'Arduino Due (Programming Port)'
Binary sketch size: 73052 bytes (used 14% of a 524288 byte maximum) (11,29 secs)

which is a huge amount of code for this little example. Even my complete CAN OBD-II project (with a small GUI and an estimated far more than thousand lines of code) written in pure C is only 43k in size. I wonder what's going on here. Also the Visual Micro hides all compiler warnings which yield additional confusings when debugging. I haven't found any settings for tweaking the IDE yet. Don't know if it is really that useful for developing CAN stuff...

Collin80

Arduino code for the Due seems to be gigantic. It takes 10,076 for the blink sketch. AnalogInOutSerial takes 26,712. The size you got for the canbus example is pretty typical for the examples. They just seem to come out that large. However, it doesn't seem to enlarge a whole lot thereafter. My whole VCU project takes up less than 100K of flash space. It has a whole lot more code than the canbus library but only takes up about 30K extra. So, I think that the arduino core library can just be a bit large. I've wondered if there is something that could be done about this but have not actually taken the time to try to figure it out. I'm being lazy because there is still all sorts of available flash space. If my sketches were getting toward 450K in size then I'd worry about how to save space.

Transistorfips

#278
Sep 24, 2013, 09:27 am Last Edit: Sep 24, 2013, 09:31 am by Transistorfips Reason: 1
Hi guys,
I think I need a idea.

I try to communicate with my OBD simulator with 29-bit EX-ID frame. 11-bit mode work fine but in 29-bit mode the sim doesn't resond. I looked on my scope and I saw the exact time for 29bit frame with 8byte payload which I calculated before. But the sim plays possum.

Here is a chunk of my code which derived from the Atmel Code example. It works fine for 11bit frame mode (I send/receive with CAN_0). Did I forget something?

Code: [Select]

void getECUData(can_mb_conf_t *p_sc_mailbox_rx, can_mb_conf_t *p_sc_mailbox_tx) {
can_reset_all_mailbox(CAN0);
reset_mailbox_conf(p_sc_mailbox_rx);

/* Init CAN0 Mailbox 1 to Reception Mailbox. */
p_sc_mailbox_rx->ul_mb_idx = TEST1_CAN_COMM_MB_IDX + 1;  //mailbox 1
p_sc_mailbox_rx->uc_obj_type = CAN_MB_RX_MODE;
p_sc_mailbox_rx->ul_id_msk = CAN_MAM_MIDvA_Msk | CAN_MAM_MIDvB_Msk; //CAN 2.0A + B
if (!eepromData[EEPROM_CAN_11_29_BIT_ID]){
p_sc_mailbox_rx->ul_id = CAN_MID_MIDvA(0x7E8);  //get 7E8 from engine control module
p_sc_mailbox_rx->uc_id_ver = 0; // 0/1: standard/extended frame
}
else  {
p_sc_mailbox_rx->ul_id = CAN_MID_MIDvB(0x7E8);  //get 7E8 from engine control module
p_sc_mailbox_rx->uc_id_ver = 1; // Ver. A/B 0/1: standard/extended frame
}
can_mailbox_init(CAN0, p_sc_mailbox_rx);

// problem starts here ---------------------------------------

/* Init CAN0 Mailbox 0 to Transmit Mailbox. */
p_sc_mailbox_tx->ul_mb_idx = TEST1_CAN_COMM_MB_IDX; //mailbox 0
p_sc_mailbox_tx->uc_obj_type = CAN_MB_TX_MODE;
p_sc_mailbox_tx->uc_tx_prio = TEST1_CAN0_TX_PRIO;
if (!eepromData[EEPROM_CAN_11_29_BIT_ID]){
p_sc_mailbox_tx->uc_id_ver = 0; // 0/1: standard/extended frame
}
else {
p_sc_mailbox_tx->uc_id_ver = 1; // Ver. A/B 0/1: standard/extended frame
printf ("DEBUG: in getECUData(); 29bit frame mode\r\n");
}
p_sc_mailbox_tx->ul_id_msk = CAN_MAM_MIDvA_Msk | CAN_MAM_MIDvB_Msk; //CAN 2.0A + B
can_mailbox_init(CAN0, p_sc_mailbox_tx);

/* Write transmit information into mailbox. */
if (!eepromData[EEPROM_CAN_11_29_BIT_ID]){  //EEPROM_CAN_11_29_BIT_ID, bit0:  0: 11bit, 1: 29bit
p_sc_mailbox_tx->ul_id = CAN_MID_MIDvA(0x7DF);  // engine control module
}
else {
p_sc_mailbox_tx->ul_id = CAN_MID_MIDvB(0x7DF);  // engine control module
printf ("DEBUG: in getECUData(); 29bit frame mode\r\n");
}
//p_sc_mailbox_tx->ul_datal = ...; set by caller
//p_sc_mailbox_tx->ul_datah = ...;
p_sc_mailbox_tx->uc_length = MAX_CAN_FRAME_DATA_LEN; // 8bytes
can_mailbox_write(CAN0, p_sc_mailbox_tx);

// problem ends here ---------------------------------------

can_enable_interrupt(CAN0, CAN_IER_MB1);

/* Send out the information in the mailbox. */
can_global_send_transfer_cmd(CAN0, CAN_TCR_MB0);

/* Wait until TX Mailbox empty. */
while (!(CAN_MSR_MRDY == (CAN_MSR_MRDY &
can_mailbox_get_status(CAN0, TEST1_CAN_COMM_MB_IDX))));
}

M2319

Hi,
I'm so glad I found this thread!  Thanks for all the hard work you guys have done.  It's a little bit confusing as to which repository is the best/latest API.  Can someone point me to the place where I can find it.  I see this link https://github.com/arduino/Arduino/tree/can/hardware/arduino/sam/libraries/CAN but it seems a little bit out of date. 

Thanks!  :smiley-mr-green: :smiley-mr-green:

Palliser


Owais

Hello,
           I am in the process of understanding the CAN library created for DUE. I am having trouble in figuring out this exact declaration :
Can*  m_pCan;

           I have seen the typ def Can in the beginning of " due_can.h " but it is only as a reference as to how the struct is defined besides that there is no other definition available of this type. Can someone please clear this up for me.

Regards.

Palliser

#282
Oct 09, 2013, 08:37 pm Last Edit: Oct 09, 2013, 08:43 pm by Palliser Reason: 1

Hello,
          I am in the process of understanding the CAN library created for DUE. I am having trouble in figuring out this exact declaration :
Can*  m_pCan;

          I have seen the typ def Can in the beginning of " due_can.h " but it is only as a reference as to how the struct is defined besides that there is no other definition available of this type. Can someone please clear this up for me.

Regards.


Hello Owais,

Can* m_pCan is a parameter of a Can function. More specifically, a defined address.
For the two Can controllers inside Arduino Due's SAM3X8E, the current CAN library (originally ported from Atmel) has defined two CAN addresses: CAN0 (0x400B4000U) and CAN1 (0x400B8000U). See sam3x8e.h file at

Quote
...\arduino-1.5.2-windows\arduino-1.5.2\hardware\arduino\sam\system\CMSIS\Device\ATMEL\sam3xa\include


Let's dissect a bit the Can* m_pCan parameter:

Can: is a structure that contains the Can hardware registers, and it is part of the component_can.h file

Quote
...\arduino-1.5.2-windows\arduino-1.5.2\hardware\arduino\sam\system\CMSIS\Device\ATMEL\sam3xa\include\component


m_pCan: is the Pointer to a CAN peripheral instance.

When we declare Can*  m_pCan, m_pCan is a variable that stores the address of a variable of the structure Can.
If for example, we want to enable the CAN controller 0. Then in the main, the function call looks like:

Quote
CAN.enable();


And that's it! but... to get a better understanding (as you requested) of the parameter, let's take a look at the original function (before the CANRaw class was created).

The call of the old function looks like:
 
Quote
can_enable(CAN0);


And the old function itself:

Code: [Select]
void can_enable(Can*  m_pCan)
{
m_pCan->CAN_MR |= CAN_MR_CANEN;
}


Where...

CAN_MR_CANEN is the CAN controller enable register. Bit 0 (0x1u << 0)
CAN_MR is the CAN mode hardware register inside the Can structure.

Thus, when we type can_enable(CAN0); we are declaring the call of the can enable function that points to the CAN controller 0 that SET the bit 0 of the enable register in the can mode hardware register inside the can structure.

Notice that all of this is transparent for the user given that all the Can functions are handle for the CANRaw class.

I hope this helps. Regards!

Owais

#283
Oct 10, 2013, 09:38 am Last Edit: Oct 10, 2013, 09:54 am by Owais Reason: 1
Thank you Palliser for taking the time to write a detailed response to my question it has helped me clear my understanding.

Just one more thing, as you have mentioned that the Can structure is from the file " component_can.h ", how/where do link this to our "due_can.h" so that the compiler knows where to look for Can structure?

Palliser


Just one more thing, as you have mentioned that the Can structure is from the file " component_can.h ", how/where do link this to our "due_can.h" so that the compiler knows where to look for Can structure?


Hello Owais,
I don't know which version of the IDE 1.5.x you are using but if you do a simple excercise of changing the name of the component_can.h file located at

Quote
...\arduino-1.5.x-windows\arduino-1.5.x\hardware\arduino\sam\system\CMSIS\Device\ATMEL\sam3xa\include\component


Let's say i.e. renaming as componen_can1.h, you will find the debugging chain showing the error. Here the simplify chain:

Quote
due_can.h->sn65hvd234.h->variant.h->Arduino.h->chip.h->sam.h->sam3.h->sam3xa.h->sam3x8e.h->component_can.h


Notice that it starts with due_can.h and then through the transceiver driver points to the variant file and so on until reach the component_can.h file that contains the Can structure.

Regards!

Go Up