CAN Transmit

Bodger62

Member
Hello,

I am transmitting a file over CAN to BusMaster, but if the time between frames in the attached sketch is reduced to lower than 150Us the data is not received correctly.

Is there any way to increase the throughput of the CAN, perhaps by checking tx ready, or some other method?

I look forward to any suggestions.

Regards,

Ray

PS: I have attempted to read the data from the SD card in RAM blocks and transmit it, but that didn't make any appreciable difference, so I think the choke point is the time between CAN transmits. Unfortunately, I can't send the file I was transmitting as it's too large.
 

Attachments

  • sketch_dec23a.ino
    6.7 KB · Views: 21
Have your tried adjusting your clk? You have FIFO setup, how about writing out to only 1 mailbox? You might add enhancefilter to prevent other mailbox's from firing interrupts on duplicates.

Code:
Can1.setMB(MB1,TX); // Set mailbox as transmit only

Can1.write(MB1, msg); // Tx FIFO

Can1.enhanceFilter(FIFO);


Code:
void Initialise_CAN_Ports(void)
{
  Can1.begin();
  Can1.setClock(CLK_60MHz); //increase clock
  Can1.setBaudRate(1000000);
  Can1.setMaxMB(16);
  Can1.enableFIFO();
  Can1.enableFIFOInterrupt();
  Can1.onReceive(can1_Sniff);
  Can1.mailboxStatus();
  Can1.enableMBInterrupts();

  Can2.begin();
  Can2.setBaudRate(1000000);
  Can2.setMaxMB(16);
  Can2.enableFIFO();
  Can2.enableFIFOInterrupt();
  Can2.onReceive(can2_Sniff);
  Can2.mailboxStatus();
  Can2.enableMBInterrupts();
}

Code:
void loop() {
  // put your main code here, to run repeatedly:
 
Can1.events();
Can2.events();

  if (send_data_state == ZIP_SEND_DATA)
  {
    Return_Zipped_Data(2);
  }
}
 
Last edited:
Let's first get something out of the way: You have a 1 million bits per second CAN bus speed set up. So, this is simple - each bit is 1 microsecond long.

You are generally sending 8 data bytes. That's 64 bits. The CAN header is long in your case because you're using 29 bit IDs so right away you have those 29 bits. Then you have around 12 other bits in the header, a 15 bit CRC, a 1 bit CRC Ack Slot, and around 10 bits required after one message until you can send the next. That's right around 131 bit times before you can send another frame. And, because of your speed, 131 microseconds. But, wait, there's more! CAN also has stuffing bits any time you have 5 consecutive bits of the same value (except in certain places). So, you're likely to have a few stuffing bits added on top. Taken all together, you aren't likely to be able to achieve better than 150 microseconds per frame no matter what you do.

I don't remember if the FIFO works for TX or only RX on this hardware. But, you are setting a TX size of 16 at the start. If I were you I'd increase that, maybe to 32 or 64. Even so, here is what I think will happen regardless:

1. Let's say you set your interframe time to 120 microseconds.
2. You send the first frame. It goes OK
3. You start to send the second one. First one isn't done yet so it's queued
4. The first frame sends and the system sees this and fires out the second
5. You start to send the third one. The second one only just started sending so this one is queued as well
6-? You keep sending at 120us but the frames take an average of 140us to send so you constantly fall more and more behind.
?+1 You hit a point where you've filled the queue you allocated but yet you want to send again. You can't.

TL;DR - You're asking too much of the CAN bus. It can only send so fast. If you want to go quicker you will need CAN-FD or some other bus which runs faster than 1Mb.
 
Thank you both for your quick responses.

I have tried the suggestions in the reply from bravo685 without any success.

I think that as CollinK has explained extremely well in his answer, the problem is that I'm asking too much of the CAN bus.

I will now try and send less data to solve my problem.

Thanks again.
 
Back
Top