MCP2515 CAN Bandwidth Limitations (commercial automotive radar)?

Hi,
I've been hacking a commercial automotive long range radar.
So far it works well, however, I'm facing issues regarding the throughput of the MCP2515 (on one of those chinese breakout boards with 8MHz crystal), and/or SPI / Arduino UNO.

The procotol is standard frames at 500kbps, the sensor is sending around 1500 frames with 8-bytes of payload per second. For continous operation, I have to the MCP in standard mode to ACK the incoming packages.

I'm using Cory's MCP library (GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library).
If just receiving and counting incoming frames, I get about 500 packages/s (out of 1200-1500 / s).

To clarify: The receive loop is running about 25.000 times per second, but only 500 times I'm getting a low CS read (or alternatively a positive CAN.checkReceive() return <-- lower throughput than digitalRead).

This is a quick example of what I'm doing:

#include <mcp_can.h>
#include <SPI.h>

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
unsigned char rxBufInverse[8];

#define CAN0_INT 2
MCP_CAN CAN0(9);

long unsigned int totalMessages=0;
unsigned long lastOutput=0;


void setup()
{
  Serial.begin(921600);
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");

  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
  Serial.println("MCP2515 Library Receive Example...");
}



void loop()
{

  if (millis()-lastOutput>=1000) {
    Serial.print("total ");
    Serial.println(totalMessages);
    totalMessages=0;
    lastOutput=millis();
  }

  if(/*CAN0.checkReceive() == CAN_MSGAVAIL*/ !digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBufInverse);      // Read data: len = data length, buf = data byte(s)
	totalMessages++;
  }
}

So does anyone have experience with high-load CAN busses?

I've been asking myself:

  • Is the 8MHz crystal sufficient for 500kbps operation?
  • Are the receive buffers correctly utilized by Cory's library?
  • The radar might be bursting out ~40 frames in less than 1ms, is the SPI communication / digitalRead fast enough to cover that? (alternatively, can an ISR be used and improve the performance)
  • If the MCP2515 isn't suited, are there alternative options for CAN transceivers (even for different microcontrollers) which are proven to be more performant?

Thanks,
Florian

Regarding the hardware, the 8MHz is within the MCP specifications.

Now, you need to remember that each CAN frame with 8bytes payload will produce a frame of avg 140bits, including headers, CRC, byte stuffing, etc. A simple math shows that at 500Kbp/s you can send no more than 3600 messages per second, or 3.6 messages per ms... so the 40 msgs in one ms burst is not doable.

I have no experience with the mentioned library, but should be ok to create a very simple program just to count and print the number os msg/s received without any payload processing, remember to use non-blocking code.

Thanks for your reply!

musskopf:
Now, you need to remember that each CAN frame with 8bytes payload will produce a frame of avg 140bits, including headers, CRC, byte stuffing, etc. A simple math shows that at 500Kbp/s you can send no more than 3600 messages per second, or 3.6 messages per ms... so the 40 msgs in one ms burst is not doable.

You're right, I've been trying to simplify the communication and my description wasn't accurate.
The radar is sending different chunks of frames with different timings.

Most important is the object list, which is sent exactly once each 66ms, saturating the bus for a few ms.
It contains 41 frames with 8 bytes of payload, with can-ids ranging from 0x740-0x768.

So what I'm receiving with an unoptimized version (Serial.print has a heavy impact) might be:

R,18957,740,8,E1,00,5F,F5,FE,01,C5,00
R,18960,746,8,00,7F,DF,FD,FF,00,0E,00
R,18962,74D,8,00,7F,DF,FD,FF,00,0E,00
R,18966,755,8,00,7F,DF,FD,FF,00,0E,00
R,18969,762,8,00,7F,DF,FD,FF,00,0E,00

The radar has actually sent the full list over those 12 ms and I've been capturing only 5 of them.
Another hurdle is that (coincidentally or due to timing constraints) frequently the same IDs are lost over a long interval (multiple continuous seconds).
It's quite unfortunate if your car is on a collision course but the object id for the obstacle is consecutively lost on the bus ;).

musskopf:
I have no experience with the mentioned library, but should be ok to create a very simple program just to count and print the number os msg/s received without any payload processing, remember to use non-blocking code.

Right now I'm just using the UNO to capture frames and forward them to a PC, who is then merging the data with live video, calculating velocity, heading and yaw rate to track obstacles in the path.

[Another custom atmega is interfacing with sensors in the car (steering angle, throttle, brake / clutch) and a PID-controlled actuator on the injection pump to adjust velocity based on the radar vision]

Serial Print will bea problem. You need to try reduce the Serial data as much as you can, like using binary. Also, user a very high speed like 1Mbp/s.

Again, do a test printing the data and another only the message count. Another option would be create a buffer/queue between the CAN and Serial print, but you might need to look into interrupts or move to a more powerful MCU... RPI with CAN is a great alternative for analysing CAN frames.

musskopf:
Serial Print will bea problem. You need to try reduce the Serial data as much as you can, like using binary. Also, user a very high speed like 1Mbp/s.

Again, do a test printing the data and another only the message count. Another option would be create a buffer/queue between the CAN and Serial print, but you might need to look into interrupts or move to a more powerful MCU... RPI with CAN is a great alternative for analysing CAN frames.

"ASCII" Serial is mainly used for debugging, so the actual microcontroller<->microcontroller communication should be fairly faster and more bandwidth efficient. Serial has always been running at ~900kbps.

An optimized version including a CAN<->Serial buffer and some timing optimizations I just tried is giving me around 70% of the data (opposed to < 30% with full debug printing and no optimizations).
That's quite nice but still not enough for production use.

Do you have any recommendation on CAN hardware for raspberry (preferably something else than MCP ICs)?
I'm almost certain it's the MCP2515 or the SPI communication which is causing issues and not the lack of processing power of the atmega.

Some radar sensors have ethernet or RS485 as an interface option.
Are you using CAN bus by choice or because it happened to be the interface on the sensor you acquired?

If you need the speed then perhaps you'll have to use something other than CAN bus.

mikb55:
Some radar sensors have ethernet or RS485 as an interface option.
Are you using CAN bus by choice or because it happened to be the interface on the sensor you acquired?

If you need the speed then perhaps you'll have to use something other than CAN bus.

This is a Continental ARS3B radar with BMW firmware, used in current BMW F10/11/30/31 models for ACC+Stop&Go and emergency brake.
So I cannot use a different interface (research versions cost $4000+) and the can protocol itself is certainly not to blame, since car manufacturers manage to interface with the sensor ;).

If you want to take a look at the specs, here's the link to the ARS300 datasheet: Home | Continental - Continental AG

It's quite a beast and easily worth $4000 - from an engineer's point of view.

If you are playing with a $4k sensor, why are you using a $10 microcontroller?

There are way faster alternatives. The Teensy 3.x boards have a built in CAN controller and run at 100+ MHz.

mikb55:
If you are playing with a $4k sensor, why are you using a $10 microcontroller?

There are way faster alternatives. The Teensy 3.x boards have a built in CAN controller and run at 100+ MHz.

I think you got me wrong there. I've purchased a commercial sensor for a BMW and paid about $150.
Over the last 8 weeks I've been reverse engineering their proprietary CAN protocol (which is actually not too sophisticated).

Continental's open research version with documented protocol costs around $4000 - that's why I went through the hassles of digging into BMW's firmware.

Thanks for your hint about the Teensy 3.x, I'll definitely take a look at it if I don't get the required performance from an atmega.