0

I am writing a program that has to handle 20000 CAN messages per second. When writing the code with python under linux using socketcan, it seems that I start to lose messages when msg_per_second is over 200.

What could be the limiting factor and how can I modify the program or OS settings to avoid losing CAN messages?

The code below shows a count of about 990 when the msg_per_second is 1000. They should be equal.

#!/usr/bin/env python3

import time
import can 
import datetime

count = 0
count_print_time = datetime.datetime.now()

bus = can.Bus(interface='socketcan', channel='vcan0', bitrate=500000)
msg = can.Message(arbitration_id=0x123, data=[1, 2, 3, 4, 5, 6], is_extended_id=True)
msg_per_second = 1000
period = 1 / msg_per_second
bus.send_periodic(msg, period)

while(True):
    bus.recv(timeout=None)
    count = count + 1

    time_elapsed = datetime.datetime.now() - count_print_time

    if time_elapsed.total_seconds() >= 1:
        count_print_time = datetime.datetime.now()
        print(f"count : {count}")
        count = 0

Output:

count : 989 count : 988 count : 988 count : 990 count : 990 count : 990 count : 990

My question might be related to the receive buffer size. When I run the following code, I always get to read 278 messages:

import can

count = 0

bus1 = can.Bus(interface='socketcan', channel='vcan0', bitrate=500000)
bus2 = can.Bus(interface='socketcan', channel='vcan0', bitrate=500000)

for i in range(1000):
    msg = can.Message(arbitration_id=i, data=[1, 2, 3, 4, 5, 6], is_extended_id=True)
    bus1.send(msg)

while(True):
    msg = bus2.recv(timeout=None)
    count = count + 1
    print(f"count: {count}") 

Output: count: 1 count: 2 ... count: 277 count: 278

I looked in the socketcan documentation and could not find information on the buffer size.

  • Print the value of `period` - is it 0? You’re doing integer arithmetic. – DisappointedByUnaccountableMod Dec 07 '20 at 19:12
  • @barny This is Python 3, it does real division by default, not integer division. – AKX Dec 07 '20 at 20:12
  • I tried using sock1.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) and it shows the buffer size as 212992. Changing this value with setsockopt does not change the behavior of the program in any way. – rickthehope Dec 08 '20 at 00:14
  • D’oh I failed that interview question :-( – DisappointedByUnaccountableMod Dec 08 '20 at 07:25
  • 2
    If you're trying to receive 20.000 CAN frames per second with a 500.000 bits/s bitrate, you have at most 25 bits per frame. The smallest possible CAN frame (11-bit identifier, no payload) is at least 47 bits. 20.000 frames/s might work in theory with 1 Mbit/s, but not in practice, even if the SocketCAN+python-can overhead was negligible, – Jos Seldenthuis Dec 10 '20 at 14:54

1 Answers1

0

Timing the recv() function, it takes from 800 to 1200 us to execute. With 1200us, this gives a maximum receiving rate of 833 msg per second.

If the receiving processing time exceeds the sending processing time, messages probably accumulate in the buffer, eventually being dropped when the buffer is full.

I have not been able to find a way to increase the buffer size. The second code snippet always gives me the last 278 messages. The rest of the messages are dropped.