Electronic – How to program 2 CAN nodes to transmit continuously in succession

buscantransmission

Suppose I have three CAN nodes: A, B and C. We know that when two nodes transmit at the same time, the node that has the least SID will prevail over the bus and the other node will have to give the bus to the first node. What I would want to do is that node B and C will continually send CAN frame to node A in succession (e.g. node B -> node A, node C -> node A, node B -> node A). Can I just assign a lower SID to B than C and just do the following code snippet?

Node B

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Node C

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Inside of the sendCANmsg, here is the snippet:

TXB0CONbits.TXREQ = 1;  // Request Message Transmission
while (TXB0CONbits.TXREQ); // Wait until message is sent.

By the way, I'm using PIC18F25k80 in implementing this. I was just thinking that after node B sent the message, when node C is about to send its message. Node B will again win the bus arbitration thus giving node C no chance of transmission. So I remedy that I can only think of is to insert a small delay like:

while(1) {
    sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);
    delay_us(10);
}

Or am I wrong? 🙂

Best Answer

Since this method brings the bus near 100% utilization, we'll assume that these 3 nodes are the only ones on the bus. Based on your delay time of 10µs, we also assume that the bus speed is 500kbps (i.e. 5 bits of delay, or 1 bit short of the post-arbitration wait between messages).

Whether the method will work or not depends largely on the implementation details of your CAN driver. A more reliable way to accomplish this would be to have node B and C waiting to read each other's message before sending (with node B initially transmitting without waiting). I.E.:

  1. Wakeup
  2. Node C waits on message B
  3. Node B transmits
  4. Node B waits on message C
  5. Node C transmits
  6. Node C waits on message B
  7. Etc.

To account for desynchronization, each waiting period should have a timeout, after which the node transmits regardless of whether it's received the other node's message.

This will even out the bus utilization and leave each controller able to accomplish other tasks while waiting for the message (instead of continually trying to transmit in the event of an arbitration loss).

Note that this is an unconventional use of CAN. You may be better served with a simpler protocol, such as SPI (node A would have to poll B and C, but there would need to be no arbitration, and everything could be DMA and/or interrupt-driven).