5
\$\begingroup\$

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? :)

\$\endgroup\$
4
\$\begingroup\$

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).

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you for your response. :) I just realized that I can use the acceptance filters just for that implementation (e.g. detecting if the other node has sent a CAN message). However, there are only 6 acceptance filters in PICf25k80 and 2 acceptance masks. If the CAN network becomes larger, somewhere less than but near 2^11 - 1, will the acceptance filters and masks suffice?I would like to hear the conventional use of CAN. :) \$\endgroup\$ – Xegara Oct 2 '13 at 13:06
  • \$\begingroup\$ I'm not sure what you mean when you say "less than but near 2^11-1". There is a practical limit on the number of nodes that can be connected to a single CAN bus due to capacitive loading--it's usually a bit over 100 nodes. A more conventional use of CAN would be an event-driven environment (with options for polling and some infrequent heartbeat-type messages). The idea is to keep the bus utilization as low as possible, though that becomes harder as more nodes are added to the bus. Your scenario is more like a drink from the fire hose, with continuous machine-gunned updates. \$\endgroup\$ – Scott Winder Oct 2 '13 at 14:13
  • \$\begingroup\$ My bad. I should have said somewhere between 0 and 2^11-1. Because the SID is 11 bits long so I think the limit of CAN network is 2^11-1. Thank you for pointing that out. I just want to know what will happen if it were to fire continuously. My real implementation is that I have 6 nodes but only one node collects the data from the other 5 nodes. So my plan is the other 5 nodes to successively send to the collector node every n milliseconds. What do you think? Is RTR a better choice? \$\endgroup\$ – Xegara Oct 2 '13 at 15:01
  • \$\begingroup\$ The question is really whether you need updates that frequently. In the case where the "master" (data-collecting node) needs only sporadic updates, and a small delay is acceptable, RTR makes sense. If the master needs immediate access to the current value, but the values change slowly, then the other nodes could just fire messages off whenever there is a change. If the values change quickly enough, they will push the bus utilization up and it may be valuable to have them sending round-robin style, as you have suggested. Just note that round-robin is not the scenario for which CAN was designed. \$\endgroup\$ – Scott Winder Oct 2 '13 at 16:28
  • \$\begingroup\$ It makes perfect sense now. I forgot that every node have different processes prior to transmitting its data to the collector-node. It makes sense to only transmit when there is a change. Thank you sir :) \$\endgroup\$ – Xegara Oct 2 '13 at 17:01
3
\$\begingroup\$

First, nodes don't have IDs, messages do.

This is tricky, and is not what CAN was designed for. It should work if each node delibrately delays a little after each succesfull transmission. I don't remember if the PIC 18F25K80 hardware lets you know when a frame is actually sent, but it probably does. The other node only needs a short window to see the end of frame and start transmitting. Once this second node starts transmitting, the first will delay its message until the next end of frame automatically anyway.

However, this sounds like a abuse of the CAN bus, and a better answer could be a re-think of the overall architecture.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you for your response. I stand corrected. I made a mistake in stating that nodes have IDs. Sorry about that. Anyways, what would that architecture be? :) \$\endgroup\$ – Xegara Oct 2 '13 at 12:49
  • \$\begingroup\$ By the way, regarding on what you said that it should work if each node deliberately delays a little after each successful transmission and once this second node starts transmitting, the first will delay its message until the next end of frame automatically anyway. Does it imply that it would work if I would only insert a small delay in Node B only, since after transmitting the CAN message from Node C, node B will win the arbitration anyways? \$\endgroup\$ – Xegara Oct 2 '13 at 12:54
  • \$\begingroup\$ @Xegara: Yes, you don't need to delay when trying to send the lowest priority message. \$\endgroup\$ – Olin Lathrop Oct 2 '13 at 13:13
  • \$\begingroup\$ Oh nice. You mentioned that this kind of implementation is not CAN was designed for. I would like to know more about the proper implementation of CAN. Where do I start? :) \$\endgroup\$ – Xegara Oct 2 '13 at 13:34
  • \$\begingroup\$ CAN is well designed for a number of nodes, each with relatively low bandwidth (compared to ethernet, for example) requirements. Lots of message can fly around, and each node listens to only what it cares about. You seem to have one controller and two dedicated data nodes. This might be better served with something like SPI where the master directly controls when each node sends data. Why do you think CAN is appropriate for your case? \$\endgroup\$ – Olin Lathrop Oct 2 '13 at 14:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.