CAN Bus Limitations


I am in the process of porting a application from netmf to microframework. (G120 -> SC20100S)

I am running into problems in regards to the CAN bus, whenever I put more than 100 messages per second on the bus, the CAN message received function is never called again. After I reduce the frequency to 100 messages again and reboot the SC20100, it receives it’s messages again.

I am running the CAN bus at 250kbps with these settings:

var propagationPhase1 = 13;
var phase2 = 2;
var baudratePrescaler = 12;
var synchronizationJumpWidth = 1;
var useMultiBitSampling = false;

Is there anything obvious that could be wrong here or is there a need of extra info? I’d love some help.

if you are using the event to receiving those messages, make sure the event is much simple as much as you can.

You can subscribe error event to see what error could be. I believe full rx or something like that.

There is can.ReadBufferSize property which you can set it higher (default 128 message), but if much thing need to be processed in event then it will full sometime, just longer.

Can you please subscribe to error events? Maybe the device is erroring out (buss off) due to bad timing.

controller.SetNominalBitTiming(new GHIElectronics.TinyCLR.Devices.Can.CanBitTiming(15 + 8, 8, 6, 8, false));

That is for 250Kbs
The clock source is 48MHz.

Thank you for the settings. I took the other settings from the can bus documentation page.

Maybe it needs to be updated to reflect the values you just gave me?

@Gus_Issa I will also subscribe to the error event to see what happens.

Thank you for the help, it’s much appreciated!

No, your values are also good. Still 250Kbs.

Just need to try optimize the receive event or poll the messages directly in a loop.

The only thing I am doing in the event is increment a counter.

I just tried with subscribing to the error event while sending 125 messages per second.

After handling 100 messages per second for a few seconds, I get the following error:
Error GHIElectronics.TinyCLR.Devices.Can.ErrorReceivedEventArgs

This means the error is triggered. How do I read the actual error though? Trying to read e.Error gives me a exception at runtime.

By reading the messages inside of the loop instead of the event, I have been able to achieve 1250 messages per second. Which, I believe is very close to the limit of 250kbps CAN.

The conclusion I can draw here is that the event is relatively slow and can’t keep up at high speeds. Is this correct?

1 Like

Yes, an error is triggered which is good.

System.Diagnostics.Debug.WriteLine("error " + ((object)e.Error).ToString());

That will tell error code.

public enum CanError
        ReadBufferOverrun = 0,
        ReadBufferFull = 1,
        BusOff = 2,
        Passive = 3

I have been able to read up to 8k messages per second at a bitrate of 1mb. This is when polling from the main loop, if using the event this does not work as well.

The only problem I’m running into right now is that at somepoint the controller.MessagesToRead property stays 0, even though there are definitely messages being sent on the bus (checked with my oscilloscope)

This happens when I try to process the messages after receiving them. All I do is take the data bytes and send them over a UDP socket to a computer. If I do this, I can process about 500 messages per second for a few seconds before the MessagesToRead property drops to 0. When it drops to 0, there is no error event triggered. It also never recovers from 0, only when I restart the microcontroller.

Things I tried to fix this but that had no results:

  • Impedance on the bus is 59.9 ohm, perfectly within CAN spec
  • I tried tinyclr 2.0 and 2.1p1
  • I tried switching socket type to tcp instead of udp

I also noticed that when the CPU runs hot, the performance get’s worse. I had multiple times where it suddenly was unable to handle 100 messages per second and when I turned it off and let it cool down for a minute, it did 500 messages per second again (only to drop to 0 again after a few seconds).

The final thing I can note is that, when the MessagesToRead property is 0, the ReadErrorCount stays 0 and the CanReadMessage stays true.

So my question here is, is the MessagesToRead property going to 0 a bug or is it something wrong on my end?

I have uploader the project I’m using here so you can test and see if you can reproduce the problem. The TinyCLR version is 2.10 preview 1 and the used cpu is the SC20100S on a custom PCB.

After implementing a watchdog like this:

 if(DateTime.Now - LastCANTime > TimeSpan.FromSeconds(1))
                    Debug.WriteLine("Resetting CAN");
                    LastCANTime = DateTime.Now;

I can verify that after resetting the CAN peripheral, I receive messages again.
However, this behaviour is very very unwanted in a CAN network. You want to be able to keep up with EVERY message and not skip a single one.

Should I create an issue on this over at the github?

yes, please add an issue.

if you dont use network (spi - wifi) does this issue happen?

Is it possible that reading 8k messages. and sending them via UDP is beyond the capacity of the device?

Have you done any basic performance testing? For example, how many UDP messages per second can the device send?

I did some testing of the event handling capacity, and found that Sitcore can handle about 2500+ events per second before the event queue begins to grow and exhaust memory.

Not a surprise that 8k/sec CAN messages cause problems.

It works when I have network initialized but not sending out the udp packet. Then this problem is not happening.

Just commenting out this line fixes it.

sock.SendTo(data, endPoint);

The issue has been created. #725

Receiving 8K CAN messages per second is very very very close to the limit of the soc. I tested this.

I wrote a program that only read available messages in the main loop, at 8K messages per second, it sometimes got behind and a small queue formed.

Not a surprise that 8k/sec CAN messages cause problems.

I agree, but the problems I am having are happening with 1k messages per second, sometimes even with 500 messages per second. I would get that the CPU would get behind and build a queue, but the actual CAN peripheral just bugs out and tries to tell me that there are zero can messages available while there defenitely are messages available. A quick reset of the CAN peripheral and everything is fine again.

Btw, the maximum UDP packages per second I’ve been able to achieve has been 2600 packets per second. This should be more than sufficient for the 500 can messages per second workload I have planned for the device. It’s just that the CAN peripheral bugs out when handling this amount of messages which is not supposed to happen.

Thanks, do you have ethernet SC20260E/D to try instead of WiFi?

When MessageToRead become 0 the system free or just CAN doesnt work?

How large data you sent over socket network?

Sorry to ask you to help but because I am not in the office today. Just collect more information before work on it.

Thanks, do you have ethernet SC20260E/D to try instead of WiFi?

I am currently using a SC20100S with ENC28J60 connected over SPI.

When MessageToRead become 0 the system free or just CAN doesnt work?

When the MessagesToRead becomes 0 everything works except for the CAN. It gets back to normal after a disable/enable.

How large data you sent over socket network?

I send the 8 data bytes of my CAN message, that is all.

Sorry to ask you to help but because I am not in the office today. Just collect more information before work on it.

No problem! I am happy to help you fix this problem. If you want, we can schedule a Zoom next week so I can show you the details and maybe we can work something out together to be included in the 2nd preview of 2.1.0 :slight_smile:

Do you see the problem in 2.0?

Yes. The same happens in 2.0.


Is there any more info available regarding this? Can I do anything more to help?
Im quite waiting on this to be fixed :slight_smile: