r/embedded•
psppb

CAN bus operation question

I’m new to CAN bus and I have inherited some code that has about 8 devices on a single CAN bus line using a Renesas RX231 chip. Currently the CAN bus is kind of what I would consider a “Free for all” whereas any device can send a command to another device. Each device also sends out pings to every other device. The master and slave relationship is still there with the master acting as sort of the “collector” of data and then the issuer of certain commands. From this I am seeing a lot of weird things like random messages being ignored or interrupts being skipped. It’s very random and not too often but when it does happen it’s a huge problem. Is this a good architecture for the CAN bus? I was thinking of trying to move it from the “free for all” state it’s currently in to a strict master/slave relationship where the master interrogates one device, waits for data, and then requests data from another. I’m not too worried this will slow things down a bit. I think what is currently happening is that two devices are trying to talk to each other at the same time and messing up messaging. Kind of like a data collision. Is this possible with CAN? My guess is yes. I’m hoping to get some solid CAN bus advice from a few individuals who have worked with CAN bus before and who can give me a good idea of how to architect the system to avoid this. Thank you!!

Posted Dec 11, 2019, 3:19 PM UTC

57
redfern314•

I haven't worked with that particular chip before, but the "free for all" method is how CAN busses typically work. CAN is multimaster specifically to enable that sort of operation. The transfer layer of the protocol (handled by the CAN controller on your micro) has a feature called arbitration, to ensure that even if 2 devices talk over each other, the higher priority message still gets transmitted and the lower can be retried later. I'd encourage you to deeply read the Wikipedia page on CAN Bus, which is surprisingly detailed!

In your case, I could see a few things happening:

  • 2 nodes are sending a message with the same ID (not supported by arbitration and may cause frame drop)
  • Bus load is too high (more than 50-70% bus utilization may cause low priority messages to be dropped)
  • RX231 is not handling interrupts fast enough (look into changing the RX mailbox settings to reduce load on microcontroller)

The last thing I'll say is that if you do move to a request-response system, that's built into the protocol. You set the RTR (remote transmission request) bit for a frame, then the other node responds with the data on the same message ID.

edit to fix formatting and add the bit about RTR

22
IJustMadeThisC | Cypress | Atmel•

To expand on your third point, the mailboxes can be set up with a filter and mask so they only receive messages with specific IDs or specific groupings of bits. The chips I work with call this the Acceptance Mask and Acceptance Code, not sure if that’s the standard naming. Setting these up will reduce the amount of interrupts and message processing, assuming each device doesn’t need to listen to everything on the bus.

3
redfern314•

Yup, thanks for the clarification. Number of interrupts can make or break your software design.

2
RamBamTyfus•

CAN has Collision Avoidance. As long as all nodes use different ID's in their messages (which they should) a collission cannot happen. The free for all approach is the most common, everyone just sends their messages repeatedly (which also makes it easy to calculate the bus load) and nodes only receive the data they want by applying filtering in their CAN controller (often this is a hardware feature).

3
got_little_clue•

Some thoughts before going ballistic:

  • Find what's the error rate, the CAN physical layer should be quite resilient to interference, if you have EE resources available ask them to check it for you, help providing capabilities to switch off or make passive specific nodes.

  • Check your bandwidth utilization, no matter what you can't beat physics.

  • What you call "free for all" is more of broadcasting with shared error checks, it only takes one node to raise an error (again, one node could have physical layer issues).

  • So, you'd usually see messages being refreshed in a CAN bus.

  • Your CAN controller/driver might have exposed retransmission policies, use them but don't abuse them, prefer "organic" refreshes.

  • Your controller/driver might expose error results when broadcasting a message, you could fine tune what to do when a message broadcast has failed (e.g. ignore if the message is going to be refreshed later)

  • Use higher priority CAN IDs (lower values) for important messages (hint: check the physical details)

  • Before building another protocol layer on top of CAN (e.g. send w/ reply), split the message into multiple IDs, change the Rx nodes to consume it in smaller blocks or even individually.

  • Anyway, refresh rate and bandwidth is a system design issue, longer and fewer broadcasting rate for non important messages, faster but not excessive rate for important ones.

  • send with reply (nodes expected to acknowledge every message) might not be the right solution, you'll consume more bandwidth, making the root cause worst and at the end you'd still have message delivery failures.

3
ArkyBeagle•

I have not used the Renexas chip, but 8 devices is not a large CAN network.

It’s very random and not too often but when it does happen it’s a huge problem.

You have to identify the bottleneck here. Based on your description, the bus isn't overly burdened. The bus arbitration inherent to CAN isn't perfect but it works quite well.

2
lmapii•

As most people pointed out - check the CAN-IDs that are used by each device. If two of them use the same then messages may collide.

Before implementing your own solutions, check if protocols like J1939 or CANopen suit your needs better (e.g., CANopen has a heartbeat feature for surveillance that could replace “ping” messages).

But these protocols might be overkill depending on what’s happening on your network. I’d suggest you try and find/create a list of messages, check which nodes send them and take it from there.

1